зеркало из https://github.com/mozilla/pjs.git
Implement Aqua form controls when building with the Cocoa toolkit (bug 188254). r=pinkerton, sr=sfraser.
This commit is contained in:
Родитель
961b2164ce
Коммит
ce58d3cee5
|
@ -56,7 +56,9 @@
|
|||
#include "nsILookAndFeel.h"
|
||||
#include "nsRegionPool.h"
|
||||
#include "nsGfxUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
static PRBool sInitializedBorders = PR_FALSE;
|
||||
|
||||
static void
|
||||
ConvertGeckoToNativeRect(const nsRect& aSrc, Rect& aDst)
|
||||
|
@ -67,102 +69,6 @@ ConvertGeckoToNativeRect(const nsRect& aSrc, Rect& aDst)
|
|||
aDst.right = aSrc.x + aSrc.width;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
GetPrimaryPresShell(nsIFrame* aFrame, nsIPresShell** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
if (!aFrame)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
content->GetDocument(*getter_AddRefs(doc));
|
||||
if (doc)
|
||||
doc->GetShellAt(0, aResult); // Addref happens here.
|
||||
}
|
||||
|
||||
|
||||
static PRInt32
|
||||
GetContentState(nsIFrame* aFrame)
|
||||
{
|
||||
if (!aFrame)
|
||||
return 0;
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
GetPrimaryPresShell(aFrame, getter_AddRefs(shell));
|
||||
if (!shell)
|
||||
return 0;
|
||||
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
shell->GetPresContext(getter_AddRefs(context));
|
||||
nsCOMPtr<nsIEventStateManager> esm;
|
||||
context->GetEventStateManager(getter_AddRefs(esm));
|
||||
PRInt32 flags = 0;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
esm->GetContentState(content, flags);
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetAttribute
|
||||
//
|
||||
// Gets the given attribute from the given frame's content node
|
||||
// and returns PR_TRUE if the attribute was found and PR_FALSE if
|
||||
// it wasn't
|
||||
//
|
||||
static PRBool
|
||||
GetAttribute(nsIFrame* aFrame, nsIAtom* inAttribute, nsCString& outValue)
|
||||
{
|
||||
if (!aFrame)
|
||||
return PR_FALSE;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
nsAutoString attr;
|
||||
nsresult res = content->GetAttr(kNameSpaceID_None, inAttribute, attr);
|
||||
outValue = NS_LossyConvertUCS2toASCII(attr).get();
|
||||
|
||||
return ( res != NS_CONTENT_ATTR_NO_VALUE &&
|
||||
!(res != NS_CONTENT_ATTR_NOT_THERE && attr.IsEmpty()));
|
||||
}
|
||||
|
||||
|
||||
static PRBool
|
||||
HasAttrValue(nsIContent* aContent, nsIAtom* aAtom, const char* aStr)
|
||||
{
|
||||
nsAutoString attr;
|
||||
aContent->GetAttr(kNameSpaceID_None, aAtom, attr);
|
||||
return attr.EqualsIgnoreCase(aStr);
|
||||
}
|
||||
|
||||
|
||||
static PRInt32
|
||||
CheckIntAttr(nsIFrame* aFrame, nsIAtom* aAtom)
|
||||
{
|
||||
nsCAutoString value;
|
||||
if ( GetAttribute(aFrame, aAtom, value) )
|
||||
return atoi(value.get());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static PRBool
|
||||
CheckBooleanAttr(nsIFrame* aFrame, nsIAtom* aAtom)
|
||||
{
|
||||
nsCAutoString value;
|
||||
GetAttribute(aFrame, aAtom, value);
|
||||
if ( GetAttribute(aFrame, aAtom, value) )
|
||||
return strcmp(value.get(), "true") == 0; // This handles the XUL case.
|
||||
else
|
||||
return PR_TRUE; // handles the HTML case where no val is true
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DoNothing
|
||||
//
|
||||
|
@ -188,21 +94,11 @@ nsNativeThemeMac::nsNativeThemeMac()
|
|||
: mEraseProc(nsnull)
|
||||
{
|
||||
mEraseProc = NewThemeEraseUPP(DoNothing);
|
||||
|
||||
mCheckedAtom = do_GetAtom("checked");
|
||||
mDisabledAtom = do_GetAtom("disabled");
|
||||
mSelectedAtom = do_GetAtom("selected");
|
||||
mDefaultAtom = do_GetAtom("default");
|
||||
mValueAtom = do_GetAtom("value");
|
||||
mModeAtom = do_GetAtom("mode");
|
||||
mOrientAtom = do_GetAtom("orient");
|
||||
mCurPosAtom = do_GetAtom("curpos");
|
||||
mMaxPosAtom = do_GetAtom("maxpos");
|
||||
mScrollbarAtom = do_GetAtom("scrollbar");
|
||||
mClassAtom = do_GetAtom("class");
|
||||
mSortDirectionAtom = do_GetAtom("sortDirection");
|
||||
mInputAtom = do_GetAtom("input");
|
||||
mInputCheckedAtom = do_GetAtom("_moz-input-checked");
|
||||
if (!sInitializedBorders) {
|
||||
sInitializedBorders = PR_TRUE;
|
||||
sTextfieldBorderSize.left = sTextfieldBorderSize.top = 2;
|
||||
sTextfieldBorderSize.right = sTextfieldBorderSize.bottom = 1;
|
||||
}
|
||||
}
|
||||
|
||||
nsNativeThemeMac::~nsNativeThemeMac()
|
||||
|
@ -211,162 +107,6 @@ nsNativeThemeMac::~nsNativeThemeMac()
|
|||
::DisposeThemeEraseUPP(mEraseProc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRBool
|
||||
nsNativeThemeMac::IsDisabled(nsIFrame* aFrame)
|
||||
{
|
||||
return CheckBooleanAttr(aFrame, mDisabledAtom);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsNativeThemeMac::IsDefaultButton(nsIFrame* aFrame)
|
||||
{
|
||||
return CheckBooleanAttr(aFrame, mDefaultAtom);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsNativeThemeMac::IsChecked(nsIFrame* aFrame, PRBool aIsHTML)
|
||||
{
|
||||
return CheckBooleanAttr(aFrame, aIsHTML ? mInputCheckedAtom : mCheckedAtom);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsNativeThemeMac::IsSelected(nsIFrame* aFrame)
|
||||
{
|
||||
return CheckBooleanAttr(aFrame, mSelectedAtom);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsNativeThemeMac::IsSortedColumn(nsIFrame* aFrame)
|
||||
{
|
||||
// if the "sortDirection" attribute is set, we're the sorted column
|
||||
nsCAutoString mode;
|
||||
if ( GetAttribute(aFrame, mSortDirectionAtom, mode) )
|
||||
return !mode.IsEmpty();
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsNativeThemeMac::IsSortReversed(nsIFrame* aFrame)
|
||||
{
|
||||
nsCAutoString mode;
|
||||
if ( GetAttribute(aFrame, mSortDirectionAtom, mode) )
|
||||
return mode.Equals("descending");
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsNativeThemeMac::DoTabsPointUp(nsIFrame* aFrame)
|
||||
{
|
||||
nsCAutoString mode;
|
||||
if ( GetAttribute(aFrame, mClassAtom, mode) )
|
||||
return mode.Find("tab-bottom") != kNotFound;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsNativeThemeMac::IsIndeterminate(nsIFrame* aFrame)
|
||||
{
|
||||
nsCAutoString mode;
|
||||
if ( GetAttribute(aFrame, mModeAtom, mode) )
|
||||
return strcmp(mode.get(), "undetermined") == 0;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetScrollbarParent
|
||||
//
|
||||
// Starting at the given frame, walk up the chain until we find the
|
||||
// top-level scrollbar, computing offsets as we go. Callers will
|
||||
// would subtract this offset from the scrollbar's coordinates
|
||||
// to draw in the current frame's coord system.
|
||||
//
|
||||
nsIFrame*
|
||||
nsNativeThemeMac::GetScrollbarParent(nsIFrame* inButton, nsPoint* outOffset)
|
||||
{
|
||||
outOffset->MoveTo(0,0);
|
||||
if ( !inButton )
|
||||
return nsnull;
|
||||
|
||||
PRBool found = PR_FALSE;
|
||||
nsIFrame* currFrame = inButton;
|
||||
do {
|
||||
// grab the content node of this frame, check if its tag is
|
||||
// |scrollbar|. If not, keep going up the chain.
|
||||
nsCOMPtr<nsIContent> content;
|
||||
currFrame->GetContent(getter_AddRefs(content));
|
||||
NS_ASSERTION(content, "Couldn't get content from frame, are we in a scrollbar?");
|
||||
if ( content ) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
content->GetTag(*getter_AddRefs(tag));
|
||||
if ( tag == mScrollbarAtom )
|
||||
found = PR_TRUE;
|
||||
else {
|
||||
// drat, add to our offset and check the parent
|
||||
nsPoint offsetFromParent;
|
||||
currFrame->GetOrigin(offsetFromParent);
|
||||
*outOffset += offsetFromParent;
|
||||
|
||||
currFrame->GetParent(&currFrame);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// hrm, no content, we're probably not in a scrollbar. just bail
|
||||
currFrame = nsnull;
|
||||
found = PR_TRUE;
|
||||
}
|
||||
} while ( !found && currFrame );
|
||||
|
||||
return currFrame;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetScrollbarParentLocalRect
|
||||
//
|
||||
// Given a child of a scrollbar, returns the parent scrollbar frame as
|
||||
// well as the rect of the parent scrollbar offset into the coordinate
|
||||
// system of the given child. A caller can turn around and pass this
|
||||
// rect directly to the AppearanceManager for drawing the entire scrollbar.
|
||||
//
|
||||
nsIFrame*
|
||||
nsNativeThemeMac::GetScrollbarParentLocalRect ( nsIFrame* inButton, nsTransform2D* inMatrix, Rect* outAdjustedRect )
|
||||
{
|
||||
::SetRect(outAdjustedRect, 0, 0, 0, 0);
|
||||
|
||||
nsPoint offset;
|
||||
nsIFrame* scrollbar = GetScrollbarParent(inButton, &offset);
|
||||
if ( scrollbar ) {
|
||||
nsRect scrollbarRect;
|
||||
scrollbar->GetRect(scrollbarRect);
|
||||
nsRect localScrollRect(-offset.x, -offset.y, scrollbarRect.width, scrollbarRect.height);
|
||||
|
||||
//printf("offset is (%ld, %ld)\n", offset.x, offset.y);
|
||||
//printf("pre-xform (%ld, %ld) w=%ld h=%ld\n", localScrollRect.x, localScrollRect.y, localScrollRect.width,
|
||||
// localScrollRect.height);
|
||||
// now that we have it in gecko coords, transform it to coords the OS can use
|
||||
inMatrix->TransformCoord(&localScrollRect.x, &localScrollRect.y,
|
||||
&localScrollRect.width, &localScrollRect.height);
|
||||
ConvertGeckoToNativeRect(localScrollRect, *outAdjustedRect);
|
||||
}
|
||||
|
||||
return scrollbar;
|
||||
}
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
@ -395,6 +135,11 @@ nsNativeThemeMac::DrawCheckbox ( const Rect& inBoxRect, PRBool inChecked, PRBool
|
|||
DrawCheckboxRadio(kThemeCheckBox, inBoxRect, inChecked, inDisabled, inState);
|
||||
}
|
||||
|
||||
void
|
||||
nsNativeThemeMac::DrawSmallCheckbox ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState )
|
||||
{
|
||||
DrawCheckboxRadio(kThemeSmallCheckBox, inBoxRect, inChecked, inDisabled, inState);
|
||||
}
|
||||
|
||||
void
|
||||
nsNativeThemeMac::DrawRadio ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState )
|
||||
|
@ -402,6 +147,11 @@ nsNativeThemeMac::DrawRadio ( const Rect& inBoxRect, PRBool inChecked, PRBool in
|
|||
DrawCheckboxRadio(kThemeRadioButton, inBoxRect, inChecked, inDisabled, inState);
|
||||
}
|
||||
|
||||
void
|
||||
nsNativeThemeMac::DrawSmallRadio ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState )
|
||||
{
|
||||
DrawCheckboxRadio(kThemeSmallRadioButton, inBoxRect, inChecked, inDisabled, inState);
|
||||
}
|
||||
|
||||
void
|
||||
nsNativeThemeMac::DrawButton ( ThemeButtonKind inKind, const Rect& inBoxRect, PRBool inIsDefault,
|
||||
|
@ -531,103 +281,6 @@ nsNativeThemeMac::DrawTab ( const Rect& inBoxRect, PRBool inIsDisabled, PRBool i
|
|||
::DrawThemeTab(&inBoxRect, style, direction, nsnull, 0L);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DrawFullScrollbar
|
||||
//
|
||||
// Draw everything in one fell swoop. Unfortunately, the AM doesn't give
|
||||
// us the ability to draw individual components. There is a routine
|
||||
// called |DrawThemeScrollBarArrows|, but it's a no-op in Aqua.
|
||||
//
|
||||
void
|
||||
nsNativeThemeMac::DrawFullScrollbar ( const Rect& inSbarRect, PRInt32 inWidgetHit, PRInt32 inLineHeight,
|
||||
PRBool inIsDisabled, PRInt32 inMax, PRInt32 inValue, PRInt32 inState )
|
||||
{
|
||||
ThemeTrackDrawInfo info;
|
||||
static Rect lastScrollbarDrawn = {0, 0, 0, 0};
|
||||
static WindowRef lastScrollbarWindow = nsnull;
|
||||
|
||||
// this is a serious, serious hack, but we seem to have some coordinate rounding problems
|
||||
// that I really can't figure out. I'll take 40 whacks for this, and even buy liquor to
|
||||
// the person that can fix it. The problem comes from the fact that we're determining the
|
||||
// location of the scrollbar's frame by walking up the frame parent chain from a child
|
||||
// of the scrollbar. Sometimes (not always) a rounding error in gfx occurs and we end up with the
|
||||
// bottom of the scrollbar being off by a pixel or two from the last time we drew it.
|
||||
// Rather nasty jiggling ensues as we draw different pieces of the scrollbar with and
|
||||
// without the rounding error. The only solution i could come up with was to remember where
|
||||
// we last drew, and if it's a close enough match, revert back to the last scrollbar rect. Seems
|
||||
// to work pretty well.
|
||||
Rect scrollbarRect = inSbarRect;
|
||||
if ( ::FrontWindow() == lastScrollbarWindow &&
|
||||
abs(scrollbarRect.bottom - lastScrollbarDrawn.bottom) <= 2 &&
|
||||
scrollbarRect.left == lastScrollbarDrawn.left )
|
||||
scrollbarRect = lastScrollbarDrawn;
|
||||
|
||||
// the scrollbar is horizontal if the width is greater than the height. Too bad the API
|
||||
// doesn't tell us which is which.
|
||||
PRBool isHorizontal =
|
||||
(scrollbarRect.right - scrollbarRect.left) > (scrollbarRect.bottom - scrollbarRect.top);
|
||||
|
||||
// compute the number of lines in our view. It's probably safe to assume that
|
||||
// the height of the scrollbar is the height of the scrollable view
|
||||
PRInt32 viewSize = isHorizontal ? (scrollbarRect.right - scrollbarRect.left) : (scrollbarRect.bottom - scrollbarRect.top);
|
||||
viewSize /= inLineHeight;
|
||||
|
||||
// Figure out if something should be drawn depressed
|
||||
//printf("-- widget drawn is %ld\n", inWidgetHit);
|
||||
ThemeTrackPressState pressState = 0L;
|
||||
if ( (inState & NS_EVENT_STATE_ACTIVE && inState & NS_EVENT_STATE_HOVER) ) {
|
||||
//printf("something is :hover:active!\n");
|
||||
switch ( inWidgetHit ) {
|
||||
case NS_THEME_SCROLLBAR_BUTTON_UP:
|
||||
pressState = kThemeTopOutsideArrowPressed;
|
||||
break;
|
||||
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
|
||||
pressState = kThemeBottomOutsideArrowPressed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//XXX can we draw inactive if we can determine if we're not in the topmost window?
|
||||
//XXX this is true for all controls, but scrollbars are the ones you notice the most
|
||||
|
||||
info.kind = kThemeMediumScrollBar;
|
||||
info.bounds = scrollbarRect;
|
||||
info.min = 0;
|
||||
info.max = inMax;
|
||||
info.value = inValue;
|
||||
info.attributes = isHorizontal ? kThemeTrackHorizontal : 0L;
|
||||
info.attributes |= kThemeTrackShowThumb;
|
||||
info.enableState = kThemeTrackActive;
|
||||
info.trackInfo.scrollbar.viewsize = viewSize;
|
||||
info.trackInfo.scrollbar.pressState = pressState;
|
||||
|
||||
::DrawThemeTrack(&info, nsnull, nsnull, 0L);
|
||||
|
||||
// update our statics for hack detection
|
||||
lastScrollbarDrawn = scrollbarRect;
|
||||
lastScrollbarWindow = ::FrontWindow();
|
||||
|
||||
//#ifdef DEBUG_PINK
|
||||
#if 1
|
||||
// some debug info for helping diagnose problems
|
||||
printf("--- BEGIN scrollbar debug info\n");
|
||||
printf("-- widget drawn is %ld\n", inWidgetHit);
|
||||
printf("bounds (%ld, %ld), (%ld, %ld)\n",inSbarRect.left, inSbarRect.top, inSbarRect.right, inSbarRect.bottom );
|
||||
printf("bounds (%ld, %ld), (%ld, %ld) adjusted\n",scrollbarRect.left, scrollbarRect.top, scrollbarRect.right, scrollbarRect.bottom );
|
||||
if ( isHorizontal )
|
||||
printf("horizontal\n");
|
||||
else
|
||||
printf("vertical\n");
|
||||
printf("viewSize %ld\n", viewSize);
|
||||
printf("max %ld\n", inMax);
|
||||
printf("value %ld\n", inValue);
|
||||
printf("pressState %x\n", pressState);
|
||||
printf("--- END scrollbar debug info\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNativeThemeMac::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType, const nsRect& aRect, const nsRect& aClipRect)
|
||||
|
@ -664,21 +317,6 @@ nsNativeThemeMac::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame*
|
|||
::ClipRect(&clipRect);
|
||||
#endif
|
||||
|
||||
PRBool isHTML = PR_FALSE;
|
||||
// for some widgets, the parent determines the appropriate state. grab the parent instead.
|
||||
if ( aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_RADIO ) {
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
if (content->IsContentOfType(nsIContent::eXUL))
|
||||
aFrame->GetParent(&aFrame);
|
||||
else {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
content->GetTag(*getter_AddRefs(tag));
|
||||
if (tag == mInputAtom)
|
||||
isHTML = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 eventState = GetContentState(aFrame);
|
||||
|
||||
switch ( aWidgetType ) {
|
||||
|
@ -690,7 +328,6 @@ nsNativeThemeMac::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame*
|
|||
break;
|
||||
|
||||
case NS_THEME_MENU:
|
||||
printf("!!! draw menu bg\n");
|
||||
::SetThemeBackground(kThemeBrushDialogBackgroundActive, 24, true);
|
||||
::EraseRect(&macRect);
|
||||
::SetThemeBackground(kThemeBrushWhite, 24, true);
|
||||
|
@ -706,12 +343,27 @@ nsNativeThemeMac::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame*
|
|||
}
|
||||
|
||||
case NS_THEME_CHECKBOX:
|
||||
DrawCheckbox ( macRect, IsChecked(aFrame, isHTML), IsDisabled(aFrame), eventState );
|
||||
DrawCheckbox ( macRect, IsChecked(aFrame), IsDisabled(aFrame), eventState );
|
||||
break;
|
||||
case NS_THEME_RADIO:
|
||||
DrawRadio ( macRect, IsSelected(aFrame), IsDisabled(aFrame), eventState );
|
||||
break;
|
||||
case NS_THEME_CHECKBOX_SMALL:
|
||||
if (transRect.height == 15) {
|
||||
// draw at 14x16, see comment in GetMinimumWidgetSize
|
||||
++macRect.bottom;
|
||||
}
|
||||
DrawSmallCheckbox ( macRect, IsChecked(aFrame), IsDisabled(aFrame), eventState );
|
||||
break;
|
||||
case NS_THEME_RADIO_SMALL:
|
||||
if (transRect.height == 14) {
|
||||
// draw at 14x15, see comment in GetMinimumWidgetSize
|
||||
++macRect.bottom;
|
||||
}
|
||||
DrawSmallRadio ( macRect, IsSelected(aFrame), IsDisabled(aFrame), eventState );
|
||||
break;
|
||||
case NS_THEME_BUTTON:
|
||||
case NS_THEME_BUTTON_SMALL:
|
||||
DrawButton ( kThemePushButton, macRect, IsDefaultButton(aFrame), IsDisabled(aFrame),
|
||||
kThemeButtonOn, kThemeAdornmentNone, eventState );
|
||||
break;
|
||||
|
@ -742,10 +394,10 @@ nsNativeThemeMac::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame*
|
|||
break;
|
||||
|
||||
case NS_THEME_PROGRESSBAR:
|
||||
DrawProgress ( macRect, IsDisabled(aFrame), IsIndeterminate(aFrame), PR_TRUE, CheckIntAttr(aFrame, mValueAtom) );
|
||||
DrawProgress ( macRect, IsDisabled(aFrame), IsIndeterminateProgress(aFrame), PR_TRUE, GetProgressValue(aFrame) );
|
||||
break;
|
||||
case NS_THEME_PROGRESSBAR_VERTICAL:
|
||||
DrawProgress ( macRect, IsDisabled(aFrame), IsIndeterminate(aFrame), PR_FALSE, CheckIntAttr(aFrame, mValueAtom) );
|
||||
DrawProgress ( macRect, IsDisabled(aFrame), IsIndeterminateProgress(aFrame), PR_FALSE, GetProgressValue(aFrame) );
|
||||
break;
|
||||
case NS_THEME_PROGRESSBAR_CHUNK:
|
||||
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
|
||||
|
@ -778,17 +430,8 @@ nsNativeThemeMac::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame*
|
|||
case NS_THEME_TREEVIEW_LINE:
|
||||
// do nothing, these lines don't exist on macos
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case NS_THEME_SCROLLBAR:
|
||||
break;
|
||||
#endif
|
||||
|
||||
case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL:
|
||||
case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL:
|
||||
// do nothing, these don't exist in aqua
|
||||
break;
|
||||
|
||||
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
|
||||
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_UP:
|
||||
|
@ -797,42 +440,16 @@ nsNativeThemeMac::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame*
|
|||
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
|
||||
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
|
||||
{
|
||||
const PRInt32 kLineHeight = 16; // should get this from the view
|
||||
|
||||
// draw the thumb and the scrollbar track. In order to do that, we
|
||||
// need to get the rect of the parent scrollbar (all we have now
|
||||
// is the rect of the thumb) in coordinates relative to the current coord
|
||||
// system. GetScrollbarParentLocalRect() will do all that for us.
|
||||
Rect macScrollbarRect;
|
||||
nsIFrame* scrollbar = GetScrollbarParentLocalRect(aFrame, transformMatrix, &macScrollbarRect);
|
||||
if ( scrollbar ) {
|
||||
// covert the scrollbar's maxpos to lines. That becomes the number of
|
||||
// clicks it takes to scroll to the bottom of the document, which is what
|
||||
// apperance wants for the max value of the scrollbar. Ensure that
|
||||
// |maxPos| is at least 1. If there really is nothing to scroll, Gecko
|
||||
// will hide the scrollbar.
|
||||
PRInt32 maxPos = CheckIntAttr(scrollbar, mMaxPosAtom) / kLineHeight;
|
||||
if ( !maxPos )
|
||||
maxPos = 1;
|
||||
PRInt32 curPos = CheckIntAttr(scrollbar, mCurPosAtom) / kLineHeight;
|
||||
|
||||
#if 0
|
||||
++macScrollbarRect.left;
|
||||
++macScrollbarRect.bottom;
|
||||
#endif
|
||||
DrawFullScrollbar ( macScrollbarRect, aWidgetType, kLineHeight, IsDisabled(aFrame),
|
||||
maxPos, curPos, eventState);
|
||||
}
|
||||
// Scrollbars are now native on mac, via nsNativeScrollbarFrame.
|
||||
// So, this should never be called.
|
||||
break;
|
||||
}
|
||||
|
||||
case NS_THEME_LISTBOX:
|
||||
DrawListBox(macRect, IsDisabled(aFrame));
|
||||
break;
|
||||
|
||||
case NS_THEME_TAB:
|
||||
DrawTab(macRect, IsDisabled(aFrame), IsSelected(aFrame), PR_TRUE, DoTabsPointUp(aFrame), eventState);
|
||||
DrawTab(macRect, IsDisabled(aFrame), IsSelected(aFrame), PR_TRUE, IsBottomTab(aFrame), eventState);
|
||||
break;
|
||||
case NS_THEME_TAB_PANELS:
|
||||
DrawTabPanel(macRect, IsDisabled(aFrame));
|
||||
|
@ -871,6 +488,11 @@ nsNativeThemeMac::GetWidgetBorder(nsIDeviceContext* aContext,
|
|||
aResult->SizeTo(5,2,5,2); // 5px for AGA
|
||||
break;
|
||||
|
||||
case NS_THEME_BUTTON_SMALL:
|
||||
aResult->SizeTo(kAquaSmallPushButtonEndcaps, kAquaPushButtonTopBottom,
|
||||
kAquaSmallPushButtonEndcaps, kAquaPushButtonTopBottom);
|
||||
break;
|
||||
|
||||
case NS_THEME_TOOLBAR_BUTTON:
|
||||
//aResult->SizeTo(5,5,5,5); // 5px around the button in aqua
|
||||
break;
|
||||
|
@ -885,11 +507,7 @@ nsNativeThemeMac::GetWidgetBorder(nsIDeviceContext* aContext,
|
|||
|
||||
case NS_THEME_TEXTFIELD:
|
||||
{
|
||||
SInt32 shadow = 0, frameOutset = 0;
|
||||
::GetThemeMetric(kThemeMetricEditTextWhitespace, &shadow);
|
||||
::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset);
|
||||
aResult->SizeTo(shadow + frameOutset, shadow + frameOutset, shadow + frameOutset,
|
||||
shadow + frameOutset);
|
||||
aResult->SizeTo(2, 2, 1, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -927,6 +545,14 @@ nsNativeThemeMac::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame*
|
|||
break;
|
||||
}
|
||||
|
||||
case NS_THEME_BUTTON_SMALL:
|
||||
{
|
||||
SInt32 buttonHeight = 0;
|
||||
::GetThemeMetric(kThemeMetricSmallPushButtonHeight, &buttonHeight);
|
||||
aResult->SizeTo(kAquaSmallPushButtonEndcaps*2, buttonHeight);
|
||||
break;
|
||||
}
|
||||
|
||||
case NS_THEME_CHECKBOX:
|
||||
{
|
||||
SInt32 boxHeight = 0, boxWidth = 0;
|
||||
|
@ -940,13 +566,38 @@ nsNativeThemeMac::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame*
|
|||
case NS_THEME_RADIO:
|
||||
{
|
||||
SInt32 radioHeight = 0, radioWidth = 0;
|
||||
::GetThemeMetric(kThemeMetricCheckBoxWidth, &radioWidth);
|
||||
::GetThemeMetric(kThemeMetricCheckBoxHeight, &radioHeight);
|
||||
::GetThemeMetric(kThemeMetricRadioButtonWidth, &radioWidth);
|
||||
::GetThemeMetric(kThemeMetricRadioButtonHeight, &radioHeight);
|
||||
aResult->SizeTo(radioWidth, radioHeight);
|
||||
*aIsOverridable = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
case NS_THEME_CHECKBOX_SMALL:
|
||||
{
|
||||
// Appearance manager (and the Aqua HIG) will tell us that a small
|
||||
// checkbox is 14x16. This includes a transparent row at the bottom
|
||||
// of the image. In order to allow the baseline for text to be aligned
|
||||
// with the bottom of the checkbox, we report the size as 14x15, but
|
||||
// we'll always tell appearance manager to draw it at 14x16. This
|
||||
// will result in Gecko aligning text with the real bottom of the
|
||||
// checkbox.
|
||||
|
||||
aResult->SizeTo(14, 15);
|
||||
*aIsOverridable = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
case NS_THEME_RADIO_SMALL:
|
||||
{
|
||||
// Same as above, but appearance manager reports 14x15, and we
|
||||
// tell gecko 14x14.
|
||||
|
||||
aResult->SizeTo(14, 14);
|
||||
*aIsOverridable = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
case NS_THEME_DROPDOWN:
|
||||
{
|
||||
SInt32 popupHeight = 0;
|
||||
|
@ -964,10 +615,9 @@ nsNativeThemeMac::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame*
|
|||
case NS_THEME_TEXTFIELD:
|
||||
{
|
||||
// at minimum, we should be tall enough for 9pt text.
|
||||
SInt32 shadow = 0, frameOutset = 0;
|
||||
::GetThemeMetric(kThemeMetricEditTextWhitespace, &shadow);
|
||||
::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset);
|
||||
aResult->SizeTo(0, (shadow + frameOutset) * 2 + 9);
|
||||
// I'm using hardcoded values here because the appearance manager
|
||||
// values for the frame size are incorrect.
|
||||
aResult->SizeTo(0, (2 + 2) /* top */ + 9 + (1 + 1) /* bottom */ );
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1089,16 +739,23 @@ PRBool
|
|||
nsNativeThemeMac::ThemeSupportsWidget(nsIPresContext* aPresContext, nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType)
|
||||
{
|
||||
// Check for specific widgets to see if HTML has overridden the style.
|
||||
#ifndef MOZ_WIDGET_COCOA
|
||||
// Only support HTML widgets for Cocoa
|
||||
if (aFrame) {
|
||||
// For now don't support HTML.
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
if (content->IsContentOfType(nsIContent::eHTML))
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aPresContext) {
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
aPresContext->GetShell(getter_AddRefs(shell));
|
||||
if (!shell->IsThemeSupportEnabled())
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// XXX We can go even further and call the API to ask if support exists.
|
||||
PRBool retVal = PR_FALSE;
|
||||
|
||||
switch ( aWidgetType ) {
|
||||
|
@ -1108,10 +765,13 @@ nsNativeThemeMac::ThemeSupportsWidget(nsIPresContext* aPresContext, nsIFrame* aF
|
|||
case NS_THEME_TOOLTIP:
|
||||
|
||||
case NS_THEME_CHECKBOX:
|
||||
case NS_THEME_CHECKBOX_SMALL:
|
||||
case NS_THEME_CHECKBOX_CONTAINER:
|
||||
case NS_THEME_RADIO:
|
||||
case NS_THEME_RADIO_SMALL:
|
||||
case NS_THEME_RADIO_CONTAINER:
|
||||
case NS_THEME_BUTTON:
|
||||
case NS_THEME_BUTTON_SMALL:
|
||||
case NS_THEME_TOOLBAR:
|
||||
case NS_THEME_STATUSBAR:
|
||||
case NS_THEME_DROPDOWN:
|
||||
|
@ -1159,8 +819,8 @@ nsNativeThemeMac::ThemeSupportsWidget(nsIPresContext* aPresContext, nsIFrame* aF
|
|||
break;
|
||||
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
||||
return retVal ? !IsWidgetStyled(aPresContext, aFrame, aWidgetType) : PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -44,9 +44,10 @@
|
|||
#include "nsIAtom.h"
|
||||
#include "nsILookAndFeel.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsNativeTheme.h"
|
||||
|
||||
|
||||
class nsNativeThemeMac : public nsITheme
|
||||
class nsNativeThemeMac : private nsNativeTheme,
|
||||
public nsITheme
|
||||
{
|
||||
public:
|
||||
nsNativeThemeMac();
|
||||
|
@ -79,7 +80,8 @@ protected:
|
|||
enum {
|
||||
kAquaPushButtonEndcaps = 14,
|
||||
kAquaPushButtonTopBottom = 2,
|
||||
|
||||
kAquaSmallPushButtonEndcaps = 10,
|
||||
|
||||
kAquaDropdownLeftEndcap = 9,
|
||||
kAquaDropwdonRightEndcap = 20 // wider on right to encompass the button
|
||||
};
|
||||
|
@ -87,25 +89,17 @@ protected:
|
|||
nsresult GetSystemColor(PRUint8 aWidgetType, nsILookAndFeel::nsColorID& aColorID);
|
||||
nsresult GetSystemFont(PRUint8 aWidgetType, nsSystemFontID& aFont);
|
||||
|
||||
PRBool IsDisabled(nsIFrame* aFrame);
|
||||
PRBool IsChecked(nsIFrame* aFrame, PRBool aIsHTML);
|
||||
PRBool IsSelected(nsIFrame* aFrame);
|
||||
PRBool IsDefaultButton(nsIFrame* aFrame);
|
||||
PRBool IsIndeterminate(nsIFrame* aFrame);
|
||||
PRBool IsSortedColumn(nsIFrame* aFrame);
|
||||
PRBool IsSortReversed(nsIFrame* aFrame);
|
||||
PRBool DoTabsPointUp(nsIFrame* aFrame);
|
||||
|
||||
// Appearance Manager drawing routines
|
||||
// Appearance Manager drawing routines
|
||||
void DrawCheckbox ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState ) ;
|
||||
void DrawSmallCheckbox ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState );
|
||||
void DrawRadio ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState ) ;
|
||||
void DrawSmallRadio ( const Rect& inBoxRect, PRBool inChecked, PRBool inDisabled, PRInt32 inState );
|
||||
void DrawToolbar ( const Rect& inBoxRect ) ;
|
||||
void DrawEditText ( const Rect& inBoxRect, PRBool inIsDisabled ) ;
|
||||
void DrawListBox ( const Rect& inBoxRect, PRBool inIsDisabled ) ;
|
||||
void DrawProgress ( const Rect& inBoxRect, PRBool inIsDisabled, PRBool inIsIndeterminate,
|
||||
PRBool inIsHorizontal, PRInt32 inValue ) ;
|
||||
void DrawFullScrollbar ( const Rect& inScrollbarRect, PRInt32 inWidgetHit, PRInt32 inLineHeight, PRBool inIsDisabled,
|
||||
PRInt32 inMax, PRInt32 inValue, PRInt32 inState ) ;
|
||||
void DrawTab ( const Rect& inBoxRect, PRBool inIsDisabled, PRBool inIsFrontmost,
|
||||
PRBool inIsHorizontal, PRBool inTabBottom, PRInt32 inState ) ;
|
||||
void DrawTabPanel ( const Rect& inBoxRect, PRBool inIsDisabled ) ;
|
||||
|
@ -117,26 +111,7 @@ protected:
|
|||
void DrawCheckboxRadio ( ThemeButtonKind inKind, const Rect& inBoxRect, PRBool inChecked,
|
||||
PRBool inDisabled, PRInt32 inState ) ;
|
||||
|
||||
// some utility routines
|
||||
nsIFrame* GetScrollbarParent(nsIFrame* inButton, nsPoint* offset);
|
||||
nsIFrame* GetScrollbarParentLocalRect(nsIFrame* inButton, nsTransform2D* inMatrix, Rect* outAdjustedRect);
|
||||
|
||||
private:
|
||||
|
||||
ThemeEraseUPP mEraseProc;
|
||||
|
||||
nsCOMPtr<nsIAtom> mCheckedAtom;
|
||||
nsCOMPtr<nsIAtom> mDisabledAtom;
|
||||
nsCOMPtr<nsIAtom> mSelectedAtom;
|
||||
nsCOMPtr<nsIAtom> mDefaultAtom;
|
||||
nsCOMPtr<nsIAtom> mValueAtom;
|
||||
nsCOMPtr<nsIAtom> mModeAtom;
|
||||
nsCOMPtr<nsIAtom> mOrientAtom;
|
||||
nsCOMPtr<nsIAtom> mCurPosAtom;
|
||||
nsCOMPtr<nsIAtom> mMaxPosAtom;
|
||||
nsCOMPtr<nsIAtom> mScrollbarAtom;
|
||||
nsCOMPtr<nsIAtom> mClassAtom;
|
||||
nsCOMPtr<nsIAtom> mSortDirectionAtom;
|
||||
nsCOMPtr<nsIAtom> mInputAtom;
|
||||
nsCOMPtr<nsIAtom> mInputCheckedAtom;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
/* -*- Mode: C++; tab-width: 2; 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@netscape.com> (Original Author)
|
||||
*
|
||||
* 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 "nsNativeTheme.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
#include "nsString.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsILookAndFeel.h"
|
||||
#include "nsThemeConstants.h"
|
||||
#include "nsIComponentManager.h"
|
||||
|
||||
nsMargin nsNativeTheme::sButtonBorderSize(2, 2, 2, 2);
|
||||
nsMargin nsNativeTheme::sButtonDisabledBorderSize(1, 1, 1, 1);
|
||||
nsMargin nsNativeTheme::sTextfieldBorderSize(2, 2, 2, 2);
|
||||
|
||||
nsNativeTheme::nsNativeTheme()
|
||||
{
|
||||
mDisabledAtom = do_GetAtom("disabled");
|
||||
mCheckedAtom = do_GetAtom("checked");
|
||||
mSelectedAtom = do_GetAtom("selected");
|
||||
mFocusedAtom = do_GetAtom("focused");
|
||||
mFirstTabAtom = do_GetAtom("first-tab");
|
||||
mDefaultAtom = do_GetAtom("default");
|
||||
mValueAtom = do_GetAtom("value");
|
||||
mModeAtom = do_GetAtom("mode");
|
||||
mClassAtom = do_GetAtom("class");
|
||||
mSortDirectionAtom = do_GetAtom("sortDirection");
|
||||
}
|
||||
|
||||
void
|
||||
nsNativeTheme::GetPrimaryPresShell(nsIFrame* aFrame, nsIPresShell** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (!aFrame)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
content->GetDocument(*getter_AddRefs(doc));
|
||||
if (doc)
|
||||
doc->GetShellAt(0, aResult); // addrefs
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsNativeTheme::GetContentState(nsIFrame* aFrame)
|
||||
{
|
||||
if (!aFrame)
|
||||
return 0;
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
GetPrimaryPresShell(aFrame, getter_AddRefs(shell));
|
||||
if (!shell)
|
||||
return 0;
|
||||
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
shell->GetPresContext(getter_AddRefs(context));
|
||||
nsCOMPtr<nsIEventStateManager> esm;
|
||||
context->GetEventStateManager(getter_AddRefs(esm));
|
||||
PRInt32 flags = 0;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
esm->GetContentState(content, flags);
|
||||
return flags;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsNativeTheme::CheckBooleanAttr(nsIFrame* aFrame, nsIAtom* aAtom)
|
||||
{
|
||||
if (!aFrame)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
nsAutoString attr;
|
||||
nsresult res = content->GetAttr(kNameSpaceID_None, aAtom, attr);
|
||||
|
||||
// For HTML elements, boolean attributes will return NOT_THERE if they
|
||||
// are not present and HAS_VALUE + a string (possibly empty)
|
||||
// if they are present.
|
||||
|
||||
// For XML/XUL elements, an attribute must be equal to the literal
|
||||
// string "true" to be counted as true. An empty string should _not_
|
||||
// be counted as true.
|
||||
|
||||
PRBool isHTML = content->IsContentOfType(nsIContent::eHTML);
|
||||
if (isHTML && (res == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
res != NS_CONTENT_ATTR_NOT_THERE && attr.IsEmpty()))
|
||||
return PR_TRUE;
|
||||
|
||||
return attr.EqualsIgnoreCase("true");
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsNativeTheme::CheckIntAttr(nsIFrame* aFrame, nsIAtom* aAtom)
|
||||
{
|
||||
if (!aFrame)
|
||||
return 0;
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
nsAutoString attr;
|
||||
content->GetAttr(kNameSpaceID_None, aAtom, attr);
|
||||
PRInt32 value;
|
||||
if (NS_FAILED(attr.ToInteger(&value)))
|
||||
return 0;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsNativeTheme::GetAttr(nsIFrame* aFrame, nsIAtom* aAtom, nsAString& attrValue)
|
||||
{
|
||||
if (!aFrame)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
nsresult res = content->GetAttr(kNameSpaceID_None, aAtom, attrValue);
|
||||
return ((res != NS_CONTENT_ATTR_NOT_THERE) &&
|
||||
!(res != NS_CONTENT_ATTR_NO_VALUE && attrValue.IsEmpty()));
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsNativeTheme::GetCheckedOrSelected(nsIFrame* aFrame, PRBool aCheckSelected)
|
||||
{
|
||||
if (!aFrame)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
|
||||
if (content->IsContentOfType(nsIContent::eXUL)) {
|
||||
// For a XUL checkbox or radio button, the state of the parent determines
|
||||
// the checked state
|
||||
aFrame->GetParent(&aFrame);
|
||||
} else {
|
||||
// Check for an HTML input element
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> inputElt = do_QueryInterface(content);
|
||||
if (inputElt) {
|
||||
PRBool checked;
|
||||
inputElt->GetChecked(&checked);
|
||||
return checked;
|
||||
}
|
||||
}
|
||||
|
||||
return CheckBooleanAttr(aFrame, aCheckSelected ? mSelectedAtom : mCheckedAtom);
|
||||
}
|
||||
|
||||
static void
|
||||
ConvertMarginToTwips(const nsMargin &aSource, nsMargin &aDest, float p2t)
|
||||
{
|
||||
aDest.top = NSIntPixelsToTwips(aSource.top, p2t);
|
||||
aDest.left = NSIntPixelsToTwips(aSource.left, p2t);
|
||||
aDest.bottom = NSIntPixelsToTwips(aSource.bottom, p2t);
|
||||
aDest.right = NSIntPixelsToTwips(aSource.right, p2t);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsNativeTheme::IsWidgetStyled(nsIPresContext* aPresContext, nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType)
|
||||
{
|
||||
// Check for specific widgets to see if HTML has overridden the style.
|
||||
if (aFrame && (aWidgetType == NS_THEME_BUTTON || aWidgetType == NS_THEME_TEXTFIELD)) {
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aFrame->GetContent(getter_AddRefs(content));
|
||||
if (content->IsContentOfType(nsIContent::eHTML)) {
|
||||
|
||||
nscolor defaultBGColor, defaultBorderColor;
|
||||
PRUint8 defaultBorderStyle;
|
||||
nsMargin defaultBorderSize;
|
||||
|
||||
float p2t;
|
||||
aPresContext->GetPixelsToTwips(&p2t);
|
||||
|
||||
nsCOMPtr<nsILookAndFeel> lookAndFeel;
|
||||
aPresContext->GetLookAndFeel(getter_AddRefs(lookAndFeel));
|
||||
if (!lookAndFeel)
|
||||
return PR_TRUE;
|
||||
|
||||
switch (aWidgetType) {
|
||||
case NS_THEME_BUTTON:
|
||||
if (IsDisabled(aFrame)) {
|
||||
ConvertMarginToTwips(sButtonDisabledBorderSize, defaultBorderSize, p2t);
|
||||
defaultBorderStyle = NS_STYLE_BORDER_STYLE_OUTSET;
|
||||
lookAndFeel->GetColor(nsILookAndFeel::eColor_threedshadow,
|
||||
defaultBorderColor);
|
||||
lookAndFeel->GetColor(nsILookAndFeel::eColor_threedface,
|
||||
defaultBGColor);
|
||||
} else {
|
||||
PRInt32 contentState = GetContentState(aFrame);
|
||||
ConvertMarginToTwips(sButtonBorderSize, defaultBorderSize, p2t);
|
||||
if (contentState & NS_EVENT_STATE_HOVER &&
|
||||
contentState & NS_EVENT_STATE_ACTIVE)
|
||||
defaultBorderStyle = NS_STYLE_BORDER_STYLE_INSET;
|
||||
else
|
||||
defaultBorderStyle = NS_STYLE_BORDER_STYLE_OUTSET;
|
||||
lookAndFeel->GetColor(nsILookAndFeel::eColor_threedface,
|
||||
defaultBorderColor);
|
||||
defaultBGColor = defaultBorderColor;
|
||||
}
|
||||
break;
|
||||
|
||||
case NS_THEME_TEXTFIELD:
|
||||
defaultBorderStyle = NS_STYLE_BORDER_STYLE_INSET;
|
||||
ConvertMarginToTwips(sTextfieldBorderSize, defaultBorderSize, p2t);
|
||||
lookAndFeel->GetColor(nsILookAndFeel::eColor_threedface,
|
||||
defaultBorderColor);
|
||||
if (IsDisabled(aFrame))
|
||||
defaultBGColor = defaultBorderColor;
|
||||
else
|
||||
lookAndFeel->GetColor(nsILookAndFeel::eColor__moz_field,
|
||||
defaultBGColor);
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ERROR("nsNativeTheme::IsWidgetStyled widget type not handled");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Check whether background differs from default
|
||||
const nsStyleBackground* ourBG;
|
||||
::GetStyleData(aFrame, &ourBG);
|
||||
|
||||
if (ourBG->mBackgroundColor != defaultBGColor ||
|
||||
ourBG->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT ||
|
||||
!(ourBG->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE))
|
||||
return PR_TRUE;
|
||||
|
||||
// Check whether border style or color differs from default
|
||||
const nsStyleBorder* ourBorder;
|
||||
::GetStyleData(aFrame, &ourBorder);
|
||||
|
||||
for (PRInt32 i = 0; i < 4; ++i) {
|
||||
if (ourBorder->GetBorderStyle(i) != defaultBorderStyle)
|
||||
return PR_TRUE;
|
||||
|
||||
PRBool borderFG, borderClear;
|
||||
nscolor borderColor;
|
||||
ourBorder->GetBorderColor(i, borderColor, borderFG, borderClear);
|
||||
if (borderColor != defaultBorderColor || borderClear)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Check whether border size differs from default
|
||||
nsMargin borderSize;
|
||||
if (ourBorder->GetBorder(borderSize) && borderSize != defaultBorderSize)
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/* -*- Mode: C++; tab-width: 2; 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@netscape.com> (Original Author)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
// This defines a common base class for nsITheme implementations, to reduce
|
||||
// code duplication.
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsMargin.h"
|
||||
|
||||
class nsIFrame;
|
||||
class nsIPresShell;
|
||||
class nsIPresContext;
|
||||
|
||||
class nsNativeTheme
|
||||
{
|
||||
protected:
|
||||
nsNativeTheme();
|
||||
|
||||
// Returns the content state (hover, focus, etc), see nsIEventStateManager.h
|
||||
PRInt32 GetContentState(nsIFrame* aFrame);
|
||||
|
||||
// Returns whether the widget is already styled by content
|
||||
// Normally called from ThemeSupportsWidget to turn off native theming
|
||||
// for elements that are already styled.
|
||||
PRBool IsWidgetStyled(nsIPresContext* aPresContext, nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType);
|
||||
|
||||
// Accessors to widget-specific state information
|
||||
|
||||
// all widgets:
|
||||
PRBool IsDisabled(nsIFrame* aFrame) {
|
||||
return CheckBooleanAttr(aFrame, mDisabledAtom);
|
||||
}
|
||||
|
||||
// button:
|
||||
PRBool IsDefaultButton(nsIFrame* aFrame) {
|
||||
return CheckBooleanAttr(aFrame, mDefaultAtom);
|
||||
}
|
||||
|
||||
// checkbox:
|
||||
PRBool IsChecked(nsIFrame* aFrame) {
|
||||
return GetCheckedOrSelected(aFrame, PR_FALSE);
|
||||
}
|
||||
|
||||
// radiobutton and tab:
|
||||
PRBool IsSelected(nsIFrame* aFrame) {
|
||||
return GetCheckedOrSelected(aFrame, PR_TRUE);
|
||||
}
|
||||
|
||||
// treeheadercell:
|
||||
PRBool IsSortedColumn(nsIFrame* aFrame) {
|
||||
nsAutoString sortdir;
|
||||
if (GetAttr(aFrame, mSortDirectionAtom, sortdir))
|
||||
return !sortdir.IsEmpty();
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool IsSortReversed(nsIFrame* aFrame) {
|
||||
nsAutoString sortdir;
|
||||
if (GetAttr(aFrame, mSortDirectionAtom, sortdir))
|
||||
return sortdir.Equals(NS_LITERAL_STRING("descending"));
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// tab:
|
||||
PRBool IsBottomTab(nsIFrame* aFrame) {
|
||||
nsAutoString classStr;
|
||||
if (GetAttr(aFrame, mClassAtom, classStr))
|
||||
return classStr.Find("tab-bottom") != kNotFound;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// progressbar:
|
||||
PRBool IsIndeterminateProgress(nsIFrame* aFrame) {
|
||||
nsAutoString mode;
|
||||
if (GetAttr(aFrame, mModeAtom, mode))
|
||||
return mode.Equals(NS_LITERAL_STRING("undetermined"));
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRInt32 GetProgressValue(nsIFrame* aFrame) {
|
||||
return CheckIntAttr(aFrame, mValueAtom);
|
||||
}
|
||||
|
||||
// textfield:
|
||||
PRBool IsReadOnly(nsIFrame* aFrame) {
|
||||
return CheckBooleanAttr(aFrame, mReadOnlyAtom);
|
||||
}
|
||||
|
||||
private:
|
||||
void GetPrimaryPresShell(nsIFrame* aFrame, nsIPresShell** aResult);
|
||||
PRBool CheckBooleanAttr(nsIFrame* aFrame, nsIAtom* aAtom);
|
||||
PRInt32 CheckIntAttr(nsIFrame* aFrame, nsIAtom* aAtom);
|
||||
PRBool GetAttr(nsIFrame* aFrame, nsIAtom* aAtom, nsAString& attrValue);
|
||||
PRBool GetCheckedOrSelected(nsIFrame* aFrame, PRBool aCheckSelected);
|
||||
|
||||
protected:
|
||||
// these are available to subclasses because they are useful in
|
||||
// implementing WidgetStateChanged()
|
||||
nsCOMPtr<nsIAtom> mDisabledAtom;
|
||||
nsCOMPtr<nsIAtom> mCheckedAtom;
|
||||
nsCOMPtr<nsIAtom> mSelectedAtom;
|
||||
|
||||
// these should be set to appropriate platform values by the subclass, to
|
||||
// match the values in platform-forms.css. These defaults match forms.css
|
||||
static nsMargin sButtonBorderSize;
|
||||
static nsMargin sButtonDisabledBorderSize;
|
||||
static nsMargin sTextfieldBorderSize;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIAtom> mFocusedAtom;
|
||||
nsCOMPtr<nsIAtom> mFirstTabAtom;
|
||||
nsCOMPtr<nsIAtom> mDefaultAtom;
|
||||
nsCOMPtr<nsIAtom> mValueAtom;
|
||||
nsCOMPtr<nsIAtom> mModeAtom;
|
||||
nsCOMPtr<nsIAtom> mClassAtom;
|
||||
nsCOMPtr<nsIAtom> mSortDirectionAtom;
|
||||
nsCOMPtr<nsIAtom> mReadOnlyAtom;
|
||||
};
|
Загрузка…
Ссылка в новой задаче