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 :
38 : #ifndef nsIView_h___
39 : #define nsIView_h___
40 :
41 : #include "nsISupports.h"
42 : #include "nsCoord.h"
43 : #include "nsRect.h"
44 : #include "nsPoint.h"
45 : #include "nsNativeWidget.h"
46 : #include "nsIWidget.h"
47 : #include "nsWidgetInitData.h"
48 : #include "nsIFrame.h"
49 :
50 : class nsIViewManager;
51 : class nsViewManager;
52 : class nsView;
53 : class nsWeakView;
54 : class nsIWidget;
55 :
56 : // Enumerated type to indicate the visibility of a layer.
57 : // hide - the layer is not shown.
58 : // show - the layer is shown irrespective of the visibility of
59 : // the layer's parent.
60 : enum nsViewVisibility {
61 : nsViewVisibility_kHide = 0,
62 : nsViewVisibility_kShow = 1
63 : };
64 :
65 : #define NS_IVIEW_IID \
66 : { 0xda62efbf, 0x0711, 0x4b79, \
67 : { 0x87, 0x85, 0x9e, 0xec, 0xed, 0xf5, 0xb0, 0x32 } }
68 :
69 : // Public view flags
70 :
71 : // Indicates that the view is using auto z-indexing
72 : #define NS_VIEW_FLAG_AUTO_ZINDEX 0x0004
73 :
74 : // Indicates that the view is a floating view.
75 : #define NS_VIEW_FLAG_FLOATING 0x0008
76 :
77 : // If set it indicates that this view should be
78 : // displayed above z-index:auto views if this view
79 : // is z-index:auto also
80 : #define NS_VIEW_FLAG_TOPMOST 0x0010
81 :
82 : //----------------------------------------------------------------------
83 :
84 : /**
85 : * View interface
86 : *
87 : * Views are NOT reference counted. Use the Destroy() member function to
88 : * destroy a view.
89 : *
90 : * The lifetime of the view hierarchy is bounded by the lifetime of the
91 : * view manager that owns the views.
92 : *
93 : * Most of the methods here are read-only. To set the corresponding properties
94 : * of a view, go through nsIViewManager.
95 : */
96 :
97 : class nsIView
98 0 : {
99 : public:
100 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_IVIEW_IID)
101 :
102 : /**
103 : * Find the view for the given widget, if there is one.
104 : * @return the view the widget belongs to, or null if the widget doesn't
105 : * belong to any view.
106 : */
107 : static nsIView* GetViewFor(nsIWidget* aWidget);
108 :
109 : /**
110 : * Get the view manager which "owns" the view.
111 : * This method might require some expensive traversal work in the future. If you can get the
112 : * view manager from somewhere else, do that instead.
113 : * @result the view manager
114 : */
115 0 : nsIViewManager* GetViewManager() const
116 0 : { return reinterpret_cast<nsIViewManager*>(mViewManager); }
117 :
118 : /**
119 : * Destroy the view.
120 : *
121 : * The view destroys its child views, and destroys and releases its
122 : * widget (if it has one).
123 : *
124 : * Also informs the view manager that the view is destroyed by calling
125 : * SetRootView(NULL) if the view is the root view and calling RemoveChild()
126 : * otherwise.
127 : */
128 : void Destroy();
129 :
130 : /**
131 : * Called to get the position of a view.
132 : * The specified coordinates are relative to the parent view's origin, but
133 : * are in appunits of this.
134 : * This is the (0, 0) origin of the coordinate space established by this view.
135 : * @param x out parameter for x position
136 : * @param y out parameter for y position
137 : */
138 0 : nsPoint GetPosition() const {
139 : // Call ExternalIsRoot here so that we can get to it from other
140 : // components
141 0 : NS_ASSERTION(!ExternalIsRoot() || (mPosX == 0 && mPosY == 0),
142 : "root views should always have explicit position of (0,0)");
143 0 : return nsPoint(mPosX, mPosY);
144 : }
145 :
146 : /**
147 : * Set the position of a view. This does not cause any invalidation. It
148 : * does reposition any widgets in this view or its descendants.
149 : */
150 : virtual void SetPosition(nscoord aX, nscoord aY) = 0;
151 :
152 : /**
153 : * Called to get the dimensions and position of the view's bounds.
154 : * The view's bounds (x,y) are relative to the origin of the parent view, but
155 : * are in appunits of this.
156 : * The view's bounds (x,y) might not be the same as the view's position,
157 : * if the view has content above or to the left of its origin.
158 : * @param aBounds out parameter for bounds
159 : */
160 0 : nsRect GetBounds() const { return mDimBounds; }
161 :
162 : /**
163 : * The bounds of this view relative to this view. So this is the same as
164 : * GetBounds except this is relative to this view instead of the parent view.
165 : */
166 0 : nsRect GetDimensions() const {
167 0 : nsRect r = mDimBounds; r.MoveBy(-mPosX, -mPosY); return r;
168 : }
169 :
170 : /**
171 : * Set the dimensions at which invalidations are clipped, which can
172 : * be different than |GetDimensions()|. |aRect| is relative to
173 : * |this|. It can be null, in which case invalidations return to
174 : * being clipped to the view dimensions.
175 : *
176 : * The caller is responsible for invalidating the area that may lie
177 : * outside the view dimensions but inside |aRect| after this call.
178 : */
179 : void SetInvalidationDimensions(const nsRect* aRect);
180 :
181 : /**
182 : * Get the offset between the coordinate systems of |this| and aOther.
183 : * Adding the return value to a point in the coordinate system of |this|
184 : * will transform the point to the coordinate system of aOther.
185 : *
186 : * The offset is expressed in appunits of |this|. So if you are getting the
187 : * offset between views in different documents that might have different
188 : * appunits per devpixel ratios you need to be careful how you use the
189 : * result.
190 : *
191 : * If aOther is null, this will return the offset of |this| from the
192 : * root of the viewmanager tree.
193 : *
194 : * This function is fastest when aOther is an ancestor of |this|.
195 : *
196 : * NOTE: this actually returns the offset from aOther to |this|, but
197 : * that offset is added to transform _coordinates_ from |this| to aOther.
198 : */
199 : nsPoint GetOffsetTo(const nsIView* aOther) const;
200 :
201 : /**
202 : * Get the offset between the origin of |this| and the origin of aWidget.
203 : * Adding the return value to a point in the coordinate system of |this|
204 : * will transform the point to the coordinate system of aWidget.
205 : *
206 : * The offset is expressed in appunits of |this|.
207 : */
208 : nsPoint GetOffsetToWidget(nsIWidget* aWidget) const;
209 :
210 : /**
211 : * Takes a point aPt that is in the coordinate system of |this|'s parent view
212 : * and converts it to be in the coordinate system of |this| taking into
213 : * account the offset and any app unit per dev pixel ratio differences.
214 : */
215 : nsPoint ConvertFromParentCoords(nsPoint aPt) const;
216 :
217 : /**
218 : * Called to query the visibility state of a view.
219 : * @result current visibility state
220 : */
221 0 : nsViewVisibility GetVisibility() const { return mVis; }
222 :
223 : /**
224 : * Get whether the view "floats" above all other views,
225 : * which tells the compositor not to consider higher views in
226 : * the view hierarchy that would geometrically intersect with
227 : * this view. This is a hack, but it fixes some problems with
228 : * views that need to be drawn in front of all other views.
229 : * @result true if the view floats, false otherwise.
230 : */
231 0 : bool GetFloating() const { return (mVFlags & NS_VIEW_FLAG_FLOATING) != 0; }
232 :
233 : /**
234 : * Called to query the parent of the view.
235 : * @result view's parent
236 : */
237 0 : nsIView* GetParent() const { return reinterpret_cast<nsIView*>(mParent); }
238 :
239 : /**
240 : * The view's first child is the child which is earliest in document order.
241 : * @result first child
242 : */
243 0 : nsIView* GetFirstChild() const { return reinterpret_cast<nsIView*>(mFirstChild); }
244 :
245 : /**
246 : * Called to query the next sibling of the view.
247 : * @result view's next sibling
248 : */
249 0 : nsIView* GetNextSibling() const { return reinterpret_cast<nsIView*>(mNextSibling); }
250 0 : void SetNextSibling(nsIView *aSibling) {
251 0 : mNextSibling = reinterpret_cast<nsView*>(aSibling);
252 0 : }
253 :
254 : /**
255 : * Set the view's frame.
256 : */
257 0 : void SetFrame(nsIFrame* aRootFrame) { mFrame = aRootFrame; }
258 :
259 : /**
260 : * Retrieve the view's frame.
261 : */
262 0 : nsIFrame* GetFrame() const { return mFrame; }
263 :
264 : /**
265 : * Get the nearest widget in this view or a parent of this view and
266 : * the offset from the widget's origin to this view's origin
267 : * @param aOffset - if non-null the offset from this view's origin to the
268 : * widget's origin (usually positive) expressed in appunits of this will be
269 : * returned in aOffset.
270 : * @return the widget closest to this view; can be null because some view trees
271 : * don't have widgets at all (e.g., printing), but if any view in the view tree
272 : * has a widget, then it's safe to assume this will not return null
273 : * XXX Remove this 'virtual' when gfx+widget are merged into gklayout;
274 : * Mac widget depends on this method, which is BOGUS!
275 : */
276 : virtual nsIWidget* GetNearestWidget(nsPoint* aOffset) const;
277 :
278 : /**
279 : * Create a widget to associate with this view. This variant of
280 : * CreateWidget*() will look around in the view hierarchy for an
281 : * appropriate parent widget for the view.
282 : *
283 : * @param aWidgetInitData data used to initialize this view's widget before
284 : * its create is called.
285 : * @return error status
286 : */
287 : nsresult CreateWidget(nsWidgetInitData *aWidgetInitData = nsnull,
288 : bool aEnableDragDrop = true,
289 : bool aResetVisibility = true);
290 :
291 : /**
292 : * Create a widget for this view with an explicit parent widget.
293 : * |aParentWidget| must be nonnull. The other params are the same
294 : * as for |CreateWidget()|.
295 : */
296 : nsresult CreateWidgetForParent(nsIWidget* aParentWidget,
297 : nsWidgetInitData *aWidgetInitData = nsnull,
298 : bool aEnableDragDrop = true,
299 : bool aResetVisibility = true);
300 :
301 : /**
302 : * Create a popup widget for this view. Pass |aParentWidget| to
303 : * explicitly set the popup's parent. If it's not passed, the view
304 : * hierarchy will be searched for an appropriate parent widget. The
305 : * other params are the same as for |CreateWidget()|, except that
306 : * |aWidgetInitData| must be nonnull.
307 : */
308 : nsresult CreateWidgetForPopup(nsWidgetInitData *aWidgetInitData,
309 : nsIWidget* aParentWidget = nsnull,
310 : bool aEnableDragDrop = true,
311 : bool aResetVisibility = true);
312 :
313 : /**
314 : * Destroys the associated widget for this view. If this method is
315 : * not called explicitly, the widget when be destroyed when its
316 : * view gets destroyed.
317 : */
318 : void DestroyWidget();
319 :
320 : /**
321 : * Attach/detach a top level widget from this view. When attached, the view
322 : * updates the widget's device context and allows the view to begin receiving
323 : * gecko events. The underlying base window associated with the widget will
324 : * continues to receive events it expects.
325 : *
326 : * An attached widget will not be destroyed when the view is destroyed,
327 : * allowing the recycling of a single top level widget over multiple views.
328 : *
329 : * @param aWidget The widget to attach to / detach from.
330 : */
331 : nsresult AttachToTopLevelWidget(nsIWidget* aWidget);
332 : nsresult DetachFromTopLevelWidget();
333 :
334 : /**
335 : * Returns a flag indicating whether the view owns it's widget
336 : * or is attached to an existing top level widget.
337 : */
338 0 : bool IsAttachedToTopLevel() const { return mWidgetIsTopLevel; }
339 :
340 : /**
341 : * In 4.0, the "cutout" nature of a view is queryable.
342 : * If we believe that all cutout view have a native widget, this
343 : * could be a replacement.
344 : * @param aWidget out parameter for widget that this view contains,
345 : * or nsnull if there is none.
346 : */
347 0 : nsIWidget* GetWidget() const { return mWindow; }
348 :
349 : /**
350 : * Returns true if the view has a widget associated with it.
351 : */
352 0 : bool HasWidget() const { return mWindow != nsnull; }
353 :
354 : /**
355 : * Make aWidget direct its events to this view.
356 : * The caller must call DetachWidgetEventHandler before this view
357 : * is destroyed.
358 : */
359 : EVENT_CALLBACK AttachWidgetEventHandler(nsIWidget* aWidget);
360 : /**
361 : * Stop aWidget directing its events to this view.
362 : */
363 : void DetachWidgetEventHandler(nsIWidget* aWidget);
364 :
365 : #ifdef DEBUG
366 : /**
367 : * Output debug info to FILE
368 : * @param out output file handle
369 : * @param aIndent indentation depth
370 : * NOTE: virtual so that debugging tools not linked into gklayout can access it
371 : */
372 : virtual void List(FILE* out, PRInt32 aIndent = 0) const;
373 : #endif // DEBUG
374 :
375 : /**
376 : * @result true iff this is the root view for its view manager
377 : */
378 : bool IsRoot() const;
379 :
380 : virtual bool ExternalIsRoot() const;
381 :
382 : void SetDeletionObserver(nsWeakView* aDeletionObserver);
383 :
384 : nsIntRect CalcWidgetBounds(nsWindowType aType);
385 :
386 : bool IsEffectivelyVisible();
387 :
388 : // This is an app unit offset to add when converting view coordinates to
389 : // widget coordinates. It is the offset in view coordinates from widget
390 : // origin (unlike views, widgets can't extend above or to the left of their
391 : // origin) to view origin expressed in appunits of this.
392 0 : nsPoint ViewToWidgetOffset() const { return mViewToWidgetOffset; }
393 :
394 : protected:
395 : friend class nsWeakView;
396 : nsViewManager *mViewManager;
397 : nsView *mParent;
398 : nsIWidget *mWindow;
399 : nsView *mNextSibling;
400 : nsView *mFirstChild;
401 : nsIFrame *mFrame;
402 : PRInt32 mZIndex;
403 : nsViewVisibility mVis;
404 : // position relative our parent view origin but in our appunits
405 : nscoord mPosX, mPosY;
406 : // relative to parent, but in our appunits
407 : nsRect mDimBounds;
408 : // in our appunits
409 : nsPoint mViewToWidgetOffset;
410 : float mOpacity;
411 : PRUint32 mVFlags;
412 : nsWeakView* mDeletionObserver;
413 : bool mWidgetIsTopLevel;
414 :
415 0 : virtual ~nsIView() {}
416 :
417 : private:
418 : nsView* Impl();
419 : const nsView* Impl() const;
420 : };
421 :
422 : NS_DEFINE_STATIC_IID_ACCESSOR(nsIView, NS_IVIEW_IID)
423 :
424 : // nsWeakViews must *not* be used in heap!
425 : class nsWeakView
426 : {
427 : public:
428 : nsWeakView(nsIView* aView) : mPrev(nsnull), mView(aView)
429 : {
430 : if (mView) {
431 : mView->SetDeletionObserver(this);
432 : }
433 : }
434 :
435 : ~nsWeakView()
436 : {
437 : if (mView) {
438 : NS_ASSERTION(mView->mDeletionObserver == this,
439 : "nsWeakViews deleted in wrong order!");
440 : // Clear deletion observer temporarily.
441 : mView->SetDeletionObserver(nsnull);
442 : // Put back the previous deletion observer.
443 : mView->SetDeletionObserver(mPrev);
444 : }
445 : }
446 :
447 : bool IsAlive() { return !!mView; }
448 :
449 : nsIView* GetView() { return mView; }
450 :
451 0 : void SetPrevious(nsWeakView* aWeakView) { mPrev = aWeakView; }
452 :
453 0 : void Clear()
454 : {
455 0 : if (mPrev) {
456 0 : mPrev->Clear();
457 : }
458 0 : mView = nsnull;
459 0 : }
460 : private:
461 : static void* operator new(size_t) CPP_THROW_NEW { return 0; }
462 : static void operator delete(void*, size_t) {}
463 : nsWeakView* mPrev;
464 : nsIView* mView;
465 : };
466 :
467 : #endif
|