Mozilla/mozilla/layout/html/forms/src/nsNativeFormControlFrame.cpp
warren%netscape.com a8b9664a8c Bug 47207. Backing out logging/PRINTF changes until we can fix stopwatch.h, introduce double parens, etc.
git-svn-id: svn://10.0.0.236/trunk@81967 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-28 22:17:53 +00:00

333 lines
9.3 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.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/NPL/
*
* 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 Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsCOMPtr.h"
#include "nsHTMLAtoms.h"
#include "nsWidgetsCID.h"
#include "nsViewsCID.h"
#include "nsIDeviceContext.h"
#include "nsIPresShell.h"
#include "nsIViewManager.h"
#include "nsIComponentManager.h"
#include "nsIFormControl.h"
#include "nsFormFrame.h"
#include "nsNativeFormControlFrame.h"
static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
nsNativeFormControlFrame::nsNativeFormControlFrame()
: nsFormControlFrame()
{
mLastMouseState = eMouseNone;
mWidget = nsnull;
}
nsNativeFormControlFrame::~nsNativeFormControlFrame()
{
NS_IF_RELEASE(mWidget);
}
NS_METHOD
nsNativeFormControlFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
if (mDidInit) {
return nsFormControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
}
nsresult result = NS_OK;
nsCOMPtr<nsIDeviceContext> dx;
aPresContext->GetDeviceContext(getter_AddRefs(dx));
PRBool requiresWidget = PR_TRUE;
// Checkto see if the device context supports widgets at all
if (dx) {
dx->SupportsNativeWidgets(requiresWidget);
}
nsWidgetRendering mode;
aPresContext->GetWidgetRenderingMode(&mode);
if ((eWidgetRendering_Gfx == mode) || (eWidgetRendering_PartialGfx == mode)) {
// Check with the frame to see if requires a widget to render
if (PR_TRUE == requiresWidget) {
RequiresWidget(requiresWidget);
}
}
if (! requiresWidget) {
return nsFormControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
}
// add ourself as an nsIFormControlFrame
if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) {
nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this));
}
GetDesiredSize(aPresContext, aReflowState, aDesiredSize, mWidgetSize);
{
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIViewManager> viewMan;
presShell->GetViewManager(getter_AddRefs(viewMan));
nsRect boundBox(0, 0, aDesiredSize.width, aDesiredSize.height);
// absolutely positioned controls already have a view but not a widget
nsIView* view = nsnull;
GetView(aPresContext, &view);
if (nsnull == view) {
result = nsComponentManager::CreateInstance(kViewCID, nsnull, kIViewIID, (void **)&view);
if (!NS_SUCCEEDED(result)) {
NS_ASSERTION(0, "Could not create view for form control");
aStatus = NS_FRAME_NOT_COMPLETE;
return result;
}
nsIFrame* parWithView;
nsIView *parView;
GetParentWithView(aPresContext, &parWithView);
parWithView->GetView(aPresContext, &parView);
// initialize the view as hidden since we don't know the (x,y) until Paint
result = view->Init(viewMan, boundBox, parView, nsnull, nsViewVisibility_kHide);
if (NS_OK != result) {
NS_ASSERTION(0, "view initialization failed");
aStatus = NS_FRAME_NOT_COMPLETE;
return NS_OK;
}
viewMan->InsertChild(parView, view, 0);
SetView(aPresContext, view);
}
PRInt32 type;
GetType(&type);
const nsIID& id = GetCID();
if ((NS_FORM_INPUT_HIDDEN != type) && (PR_TRUE == requiresWidget)) {
// Do the following only if a widget is created
nsWidgetInitData* initData = GetWidgetInitData(aPresContext); // needs to be deleted
view->CreateWidget(id, initData);
if (nsnull != initData) {
delete(initData);
}
// set our widget
result = GetWidget(view, &mWidget);
if ((PR_FALSE == NS_SUCCEEDED(result)) || (nsnull == mWidget)) { // keep the ref on mWidget
NS_ASSERTION(0, "could not get widget");
}
}
PostCreateWidget(aPresContext, aDesiredSize.width, aDesiredSize.height);
mDidInit = PR_TRUE;
if ((aDesiredSize.width != boundBox.width) || (aDesiredSize.height != boundBox.height)) {
viewMan->ResizeView(view, aDesiredSize.width, aDesiredSize.height);
}
}
aDesiredSize.ascent = aDesiredSize.height;
aDesiredSize.descent = 0;
if (nsnull != aDesiredSize.maxElementSize) {
//XXX aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding);
}
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
NS_IMETHODIMP
nsNativeFormControlFrame::AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint)
{
if (mWidget) {
if (nsHTMLAtoms::disabled == aAttribute) {
mWidget->Enable(!nsFormFrame::GetDisabled(this));
}
}
return NS_OK;
}
void
nsNativeFormControlFrame::SetColors(nsIPresContext* aPresContext)
{
if (mWidget) {
nsCompatibility mode;
aPresContext->GetCompatibilityMode(&mode);
const nsStyleColor* color =
(const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
if (nsnull != color) {
if (!(NS_STYLE_BG_COLOR_TRANSPARENT & color->mBackgroundFlags)) {
mWidget->SetBackgroundColor(color->mBackgroundColor);
#ifdef bug_1021_closed
} else if (eCompatibility_NavQuirks == mode) {
#else
} else {
#endif
mWidget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF));
}
mWidget->SetForegroundColor(color->mColor);
}
}
}
// native widgets don't need to repaint
void
nsNativeFormControlFrame::SetFocus(PRBool aOn, PRBool aRepaint)
{
if (mWidget) {
if (aOn) {
mWidget->SetFocus();
}
else {
//Unsetting of focus on native widget is accomplised
//by pushing focus up to its parent
nsIWidget *parentWidget = mWidget->GetParent();
if (parentWidget) {
parentWidget->SetFocus();
NS_RELEASE(parentWidget);
}
}
}
}
nsresult
nsNativeFormControlFrame::GetWidget(nsIWidget** aWidget)
{
if (mWidget) {
NS_ADDREF(mWidget);
*aWidget = mWidget;
mWidget->Enable(!nsFormFrame::GetDisabled(this));
return NS_OK;
} else {
*aWidget = nsnull;
return NS_FORM_NOTOK;
}
}
nsresult
nsNativeFormControlFrame::GetWidget(nsIView* aView, nsIWidget** aWidget)
{
nsIWidget* widget;
aView->GetWidget(widget);
nsresult result;
if (nsnull == widget) {
*aWidget = nsnull;
result = NS_ERROR_FAILURE;
} else {
result = widget->QueryInterface(kIWidgetIID, (void**)aWidget); // keep the ref
if (NS_FAILED(result)) {
NS_ASSERTION(0, "The widget interface is invalid"); // need to print out more details of the widget
}
NS_RELEASE(widget);
}
return result;
}
NS_METHOD nsNativeFormControlFrame::HandleEvent(nsIPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
if (nsnull == mWidget) {
return nsFormControlFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
return NS_OK;
}
// make sure that the widget in the event is this input
// XXX if there is no view, it could be an image button. Unfortunately,
// every image button will get every event.
nsIView* view;
GetView(aPresContext, &view);
if (view) {
if (mWidget != aEvent->widget) {
*aEventStatus = nsEventStatus_eIgnore;
return NS_OK;
}
}
// if not native then use the NS_MOUSE_LEFT_CLICK to see if pressed
// unfortunately native widgets don't seem to handle this right.
// so use the old code for native stuff. -EDV
//printf(" %d %d %d %d (%d,%d) \n", this, aEvent->widget, aEvent->widgetSupports,
// aEvent->message, aEvent->point.x, aEvent->point.y);
PRInt32 type;
GetType(&type);
switch (aEvent->message) {
case NS_MOUSE_ENTER_SYNTH:
mLastMouseState = eMouseEnter;
break;
case NS_MOUSE_LEFT_BUTTON_DOWN:
mLastMouseState = eMouseDown;
break;
case NS_MOUSE_LEFT_BUTTON_UP:
if (eMouseDown == mLastMouseState) {
MouseClicked(aPresContext);
}
mLastMouseState = eMouseEnter;
break;
case NS_MOUSE_EXIT_SYNTH:
mLastMouseState = eMouseNone;
break;
case NS_CONTROL_CHANGE:
ControlChanged(aPresContext);
break;
case NS_KEY_DOWN:
return nsFormControlFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
*aEventStatus = nsEventStatus_eConsumeDoDefault;
return NS_OK;
}