1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 : #include "nsCOMPtr.h"
38 : #include "nsImageFrame.h"
39 : #include "nsIFormControlFrame.h"
40 : #include "nsIFormControl.h"
41 : #include "nsHTMLParts.h"
42 : #include "nsPresContext.h"
43 : #include "nsIPresShell.h"
44 : #include "nsStyleContext.h"
45 : #include "nsLeafFrame.h"
46 : #include "nsCSSRendering.h"
47 : #include "nsISupports.h"
48 : #include "nsGkAtoms.h"
49 : #include "nsStyleConsts.h"
50 : #include "nsFormControlFrame.h"
51 : #include "nsGUIEvent.h"
52 : #include "nsIServiceManager.h"
53 : #include "nsContainerFrame.h"
54 : #include "nsLayoutUtils.h"
55 : #ifdef ACCESSIBILITY
56 : #include "nsAccessibilityService.h"
57 : #endif
58 :
59 : void
60 0 : IntPointDtorFunc(void *aObject, nsIAtom *aPropertyName,
61 : void *aPropertyValue, void *aData)
62 : {
63 0 : nsIntPoint *propertyValue = static_cast<nsIntPoint*>(aPropertyValue);
64 : delete propertyValue;
65 0 : }
66 :
67 :
68 : #define nsImageControlFrameSuper nsImageFrame
69 : class nsImageControlFrame : public nsImageControlFrameSuper,
70 : public nsIFormControlFrame
71 : {
72 : public:
73 : nsImageControlFrame(nsStyleContext* aContext);
74 : ~nsImageControlFrame();
75 :
76 : virtual void DestroyFrom(nsIFrame* aDestructRoot);
77 : NS_IMETHOD Init(nsIContent* aContent,
78 : nsIFrame* aParent,
79 : nsIFrame* aPrevInFlow);
80 :
81 : NS_DECL_QUERYFRAME
82 : NS_DECL_FRAMEARENA_HELPERS
83 :
84 : NS_IMETHOD Reflow(nsPresContext* aPresContext,
85 : nsHTMLReflowMetrics& aDesiredSize,
86 : const nsHTMLReflowState& aReflowState,
87 : nsReflowStatus& aStatus);
88 :
89 : NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
90 : nsGUIEvent* aEvent,
91 : nsEventStatus* aEventStatus);
92 :
93 : virtual nsIAtom* GetType() const;
94 :
95 : #ifdef ACCESSIBILITY
96 : virtual already_AddRefed<nsAccessible> CreateAccessible();
97 : #endif
98 :
99 : #ifdef DEBUG
100 0 : NS_IMETHOD GetFrameName(nsAString& aResult) const {
101 0 : return MakeFrameName(NS_LITERAL_STRING("ImageControl"), aResult);
102 : }
103 : #endif
104 :
105 : NS_IMETHOD GetCursor(const nsPoint& aPoint,
106 : nsIFrame::Cursor& aCursor);
107 : // nsIFormContromFrame
108 : virtual void SetFocus(bool aOn, bool aRepaint);
109 : virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue);
110 : virtual nsresult GetFormProperty(nsIAtom* aName, nsAString& aValue) const;
111 : };
112 :
113 :
114 0 : nsImageControlFrame::nsImageControlFrame(nsStyleContext* aContext):
115 0 : nsImageControlFrameSuper(aContext)
116 : {
117 0 : }
118 :
119 0 : nsImageControlFrame::~nsImageControlFrame()
120 : {
121 0 : }
122 :
123 : void
124 0 : nsImageControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
125 : {
126 0 : if (!GetPrevInFlow()) {
127 0 : nsFormControlFrame::RegUnRegAccessKey(this, false);
128 : }
129 0 : nsImageControlFrameSuper::DestroyFrom(aDestructRoot);
130 0 : }
131 :
132 : nsIFrame*
133 0 : NS_NewImageControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
134 : {
135 0 : return new (aPresShell) nsImageControlFrame(aContext);
136 : }
137 :
138 0 : NS_IMPL_FRAMEARENA_HELPERS(nsImageControlFrame)
139 :
140 : NS_IMETHODIMP
141 0 : nsImageControlFrame::Init(nsIContent* aContent,
142 : nsIFrame* aParent,
143 : nsIFrame* aPrevInFlow)
144 : {
145 0 : nsresult rv = nsImageControlFrameSuper::Init(aContent, aParent, aPrevInFlow);
146 0 : NS_ENSURE_SUCCESS(rv, rv);
147 :
148 : // nsIntPoint allocation can fail, in which case we just set the property
149 : // to null, which is safe
150 0 : if (aPrevInFlow) {
151 0 : return NS_OK;
152 : }
153 :
154 : return mContent->SetProperty(nsGkAtoms::imageClickedPoint,
155 0 : new nsIntPoint(0, 0),
156 0 : IntPointDtorFunc);
157 : }
158 :
159 0 : NS_QUERYFRAME_HEAD(nsImageControlFrame)
160 0 : NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
161 0 : NS_QUERYFRAME_TAIL_INHERITING(nsImageControlFrameSuper)
162 :
163 : #ifdef ACCESSIBILITY
164 : already_AddRefed<nsAccessible>
165 0 : nsImageControlFrame::CreateAccessible()
166 : {
167 0 : nsAccessibilityService* accService = nsIPresShell::AccService();
168 0 : if (accService) {
169 0 : if (mContent->Tag() == nsGkAtoms::button ||
170 0 : mContent->Tag() == nsGkAtoms::input) {
171 : return accService->CreateHTMLButtonAccessible(mContent,
172 0 : PresContext()->PresShell());
173 : }
174 : }
175 :
176 0 : return nsnull;
177 : }
178 : #endif
179 :
180 : nsIAtom*
181 0 : nsImageControlFrame::GetType() const
182 : {
183 0 : return nsGkAtoms::imageControlFrame;
184 : }
185 :
186 : NS_METHOD
187 0 : nsImageControlFrame::Reflow(nsPresContext* aPresContext,
188 : nsHTMLReflowMetrics& aDesiredSize,
189 : const nsHTMLReflowState& aReflowState,
190 : nsReflowStatus& aStatus)
191 : {
192 0 : DO_GLOBAL_REFLOW_COUNT("nsImageControlFrame");
193 0 : DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
194 0 : if (!GetPrevInFlow() && (mState & NS_FRAME_FIRST_REFLOW)) {
195 0 : nsFormControlFrame::RegUnRegAccessKey(this, true);
196 : }
197 0 : return nsImageControlFrameSuper::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
198 : }
199 :
200 : NS_METHOD
201 0 : nsImageControlFrame::HandleEvent(nsPresContext* aPresContext,
202 : nsGUIEvent* aEvent,
203 : nsEventStatus* aEventStatus)
204 : {
205 0 : NS_ENSURE_ARG_POINTER(aEventStatus);
206 :
207 : // Don't do anything if the event has already been handled by someone
208 0 : if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
209 0 : return NS_OK;
210 : }
211 :
212 : // do we have user-input style?
213 0 : const nsStyleUserInterface* uiStyle = GetStyleUserInterface();
214 0 : if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE || uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED)
215 0 : return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
216 :
217 0 : if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) { // XXX cache disabled
218 0 : return NS_OK;
219 : }
220 :
221 0 : *aEventStatus = nsEventStatus_eIgnore;
222 :
223 0 : if (aEvent->eventStructType == NS_MOUSE_EVENT &&
224 : aEvent->message == NS_MOUSE_BUTTON_UP &&
225 : static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton) {
226 : // Store click point for nsHTMLInputElement::SubmitNamesValues
227 : // Do this on MouseUp because the specs don't say and that's what IE does
228 : nsIntPoint* lastClickPoint =
229 : static_cast<nsIntPoint*>
230 0 : (mContent->GetProperty(nsGkAtoms::imageClickedPoint));
231 0 : if (lastClickPoint) {
232 : // normally lastClickedPoint is not null, as it's allocated in Init()
233 0 : nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
234 0 : TranslateEventCoords(pt, *lastClickPoint);
235 : }
236 : }
237 : return nsImageControlFrameSuper::HandleEvent(aPresContext, aEvent,
238 0 : aEventStatus);
239 : }
240 :
241 : void
242 0 : nsImageControlFrame::SetFocus(bool aOn, bool aRepaint)
243 : {
244 0 : }
245 :
246 : NS_IMETHODIMP
247 0 : nsImageControlFrame::GetCursor(const nsPoint& aPoint,
248 : nsIFrame::Cursor& aCursor)
249 : {
250 : // Use style defined cursor if one is provided, otherwise when
251 : // the cursor style is "auto" we use the pointer cursor.
252 0 : FillCursorInformationFromStyle(GetStyleUserInterface(), aCursor);
253 :
254 0 : if (NS_STYLE_CURSOR_AUTO == aCursor.mCursor) {
255 0 : aCursor.mCursor = NS_STYLE_CURSOR_POINTER;
256 : }
257 :
258 0 : return NS_OK;
259 : }
260 :
261 : nsresult
262 0 : nsImageControlFrame::SetFormProperty(nsIAtom* aName,
263 : const nsAString& aValue)
264 : {
265 0 : return NS_OK;
266 : }
267 :
268 : nsresult
269 0 : nsImageControlFrame::GetFormProperty(nsIAtom* aName,
270 : nsAString& aValue) const
271 : {
272 0 : aValue.Truncate();
273 0 : return NS_OK;
274 : }
|