2009-12-07 Rolf Bjarne Kvinge <RKvinge@novell.com>
[moon.git] / src / uielement.h
blob26a0fa0885e48c86b25a0428bd0ba04b0b36cd2c
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * uielement.h
5 * Contact:
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007-2009 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
14 #ifndef __MOON_UIELEMENT_H__
15 #define __MOON_UIELEMENT_H__
17 #include <glib.h>
19 #include "dependencyobject.h"
20 #include "resources.h"
21 #include "point.h"
22 #include "rect.h"
23 #include "region.h"
24 #include "list.h"
25 #include "size.h"
26 #include "layoutinformation.h"
28 #define QUANTUM_ALPHA 1
30 #if QUANTUM_ALPHA
31 #define IS_TRANSLUCENT(x) (x * 255 < 254.5)
32 #define IS_INVISIBLE(x) (x * 255 < .5)
33 #else
34 #define IS_TRANSLUCENT(x) (x < 1.0)
35 #define IS_INVISIBLE(x) (x <= 0.0)
36 #endif
38 class Surface;
40 /* @Namespace=System.Windows */
41 class UIElement : public DependencyObject {
42 public:
43 UIElement ();
44 virtual void Dispose ();
46 int dirty_flags;
47 List::Node *up_dirty_node;
48 List::Node *down_dirty_node;
50 bool force_invalidate_of_new_bounds;
51 bool emitting_loaded;
53 Region *dirty_region;
55 int DumpHierarchy (UIElement *obj);
57 enum UIElementFlags {
58 NONE = 0x00,
59 IS_LOADED = 0x01,
61 // these two flags correspond to the 2 states of VisibilityProperty
62 RENDER_VISIBLE = 0x02,
64 // the HitTestVisible property
65 HIT_TEST_VISIBLE = 0x04,
67 TOTAL_RENDER_VISIBLE = 0x08,
68 TOTAL_HIT_TEST_VISIBLE = 0x10,
70 SHAPE_EMPTY = 0x20, // there's is nothing to draw, the cached path may be NULL
71 SHAPE_NORMAL = 0x40, // normal drawing
72 SHAPE_DEGENERATE = 0x80, // degenerate drawing, use the Stroke brush for filling
73 SHAPE_RADII = 0x100,
74 SHAPE_MASK = (SHAPE_EMPTY | SHAPE_NORMAL | SHAPE_DEGENERATE | SHAPE_RADII),
76 // this means the element will be emitting OnLoaded
77 // shortly, and any child added to the element while
78 // it is in this state should post Loaded as well.
79 PENDING_LOADED = 0x200,
81 WALKED_FOR_LOADED = 0x400,
83 // These are flags which are propagated up the visual tree so that
84 // the layout update pass knows which branches need processing.
85 DIRTY_ARRANGE_HINT = 0x800,
86 DIRTY_MEASURE_HINT = 0x1000,
87 DIRTY_SIZE_HINT = 0x2000
90 virtual TimeManager *GetTimeManager ();
92 virtual bool PermitsMultipleParents () { return false; }
94 virtual void SetVisualParent (UIElement *visual_parent);
95 /* @GenerateCBinding,GeneratePInvoke */
96 UIElement *GetVisualParent () { return visual_parent; }
98 int GetVisualLevel () { return visual_level; }
99 void SetVisualLevel (int level) { visual_level = level; }
101 /* @GenerateCBinding,GeneratePInvoke,ManagedAccess=Internal */
102 virtual void SetSubtreeObject (DependencyObject *value);
104 /* @GenerateCBinding,GeneratePInvoke,ManagedAccess=Internal */
105 virtual DependencyObject *GetSubtreeObject () { return subtree_object; }
107 /* @GenerateCBinding,GeneratePInvoke */
108 virtual void ElementAdded (UIElement *obj);
109 /* @GenerateCBinding,GeneratePInvoke */
110 virtual void ElementRemoved (UIElement *obj);
112 virtual bool EnableAntiAlias() { return true; }
114 virtual void SetIsAttached (bool value);
116 // UpdateTotalRenderVisibility:
117 // Updates the opacity and render visibility on this item based on
118 // its parent's opacity and visibility as well as the value of its
119 // OpacityProperty and RenderVisibilityProperty.
121 void UpdateTotalRenderVisibility ();
122 void ComputeTotalRenderVisibility ();
123 bool GetActualTotalRenderVisibility ();
126 // GetRenderVisible:
127 // Returns true if the Visibility property of this item is "Visible", and false otherwise
129 bool GetRenderVisible () { return (flags & UIElement::TOTAL_RENDER_VISIBLE) != 0; }
132 // UpdateTotalHitTestVisibility:
133 // Updates the hit testability of the item based on the you know..
134 // The hit test flag.
135 void UpdateTotalHitTestVisibility ();
136 void ComputeTotalHitTestVisibility ();
137 bool GetActualTotalHitTestVisibility ();
140 // GetHitTestVisible:
141 // Returns true if the IsHitTestVisible property of this item true, and false otherwise
143 bool GetHitTestVisible () { return (flags & UIElement::TOTAL_HIT_TEST_VISIBLE) != 0; }
146 // UpdateTransform:
147 // Updates the absolute_xform for this item
149 void UpdateTransform ();
150 void ComputeLocalTransform ();
151 void ComputeTransform ();
152 virtual void TransformBounds (cairo_matrix_t *old, cairo_matrix_t *current);
155 // IsLoaded:
156 // Returns true if the element has been attached to a
157 // surface and is part of the visual hierarchy.
159 bool IsLoaded () { return (flags & UIElement::IS_LOADED) != 0; }
160 void ClearLoaded ();
162 bool HasBeenWalkedForLoaded () { return (flags & UIElement::WALKED_FOR_LOADED) != 0; }
163 void ClearWalkedForLoaded () { flags &= ~UIElement::WALKED_FOR_LOADED; }
164 void SetWalkedForLoaded () { flags |= UIElement::WALKED_FOR_LOADED; }
166 void ClearFlag (UIElementFlags flag) { flags &= ~flag; }
167 bool HasFlag (UIElementFlags flag) { return (flags & flag) == flag; }
168 void SetFlag (UIElementFlags flag) { flags |= flag; }
169 void PropagateFlagUp (UIElementFlags flag);
172 // Render:
173 // Renders the given @item on the @surface. the area that is
174 // exposed is delimited by x, y, width, height
176 virtual void Render (cairo_t *cr, Region *region, bool path_only = false);
179 // Paint:
180 // Do an optimized render pass on the this element and it's
181 // subtree.
183 void Paint (cairo_t *cr, Region *region, cairo_matrix_t *matrix);
185 // a non virtual method for use when we want to wrap render
186 // with debugging and/or timing info
187 void DoRender (cairo_t *cr, Region *region);
188 bool UseBackToFront ();
191 // GetSizeForBrush:
192 // Gets the size of the area to be painted by a Brush (needed for image/video scaling)
193 virtual void GetSizeForBrush (cairo_t *cr, double *width, double *height);
196 // GetOriginPoint:
197 // Gets real origin, required e.g. for lineargradientbrushes on Path
198 virtual Point GetOriginPoint ()
200 return Point (0.0, 0.0);
204 // ShiftPosition:
206 // This method should actually set the x/y of the bounds
207 // rectangle to the new position. It is virtual to allow
208 // subclasses with specialized bounds (Panel, InkPresenter)
209 // the opportunity to set those bounds' positions as well.
211 virtual void ShiftPosition (Point p);
214 // UpdateBounds:
215 // Recomputes the bounds of this element, and if they're
216 // different chains up to its parent telling it to update
217 // its bounds.
219 void UpdateBounds (bool force_redraw_of_new_bounds = false);
221 // ComputeBounds:
222 // Updates the bounding box for the given item, this uses the parent
223 // chain to compute the composite affine.
225 // Output:
226 // item->bounds is updated
228 virtual void ComputeBounds ();
231 // GetBounds:
232 // returns the current bounding box for the given item in surface
233 // coordinates.
235 Rect GetBounds () { return bounds; }
238 // GetSubtreeBounds:
239 // returns the bounding box including all sub-uielements.
240 // implemented by containers in surface coordinates.
242 virtual Rect GetSubtreeBounds () { return bounds; }
245 // GetRenderBounds:
246 // returns the bounding box to be rendered, which
247 // unfortunately isn't necessarily the same as either our
248 // bounds or subtree bounds (in the case of inkpresenter)
249 virtual Rect GetRenderBounds () { return bounds; }
252 // GetCoverageBounds:
253 // returns the bounding box in global coordinates that opaquely covered by this object
255 virtual Rect GetCoverageBounds () { return Rect (); }
259 // IsLayoutContainer:
260 // returns true if the container has children that require a measure
261 // pass.
262 virtual bool IsLayoutContainer () { return GetSubtreeObject () != NULL; }
263 virtual bool IsContainer () { return IsLayoutContainer (); }
265 // HitTest
267 // Accumulate a list of all elements that will contain the
268 // point (or intersect the rectangle). The first node in the
269 // list is the most deeply nested node, the last node is the
270 // root.
271 virtual void HitTest (cairo_t *cr, Point p, List *uielement_list);
272 virtual void HitTest (cairo_t *cr, Rect r, List *uielement_list);
274 /* @GenerateCBinding,GeneratePInvoke */
275 void FindElementsInHostCoordinates_p (Point p, HitTestCollection *uielement_list);
276 /* @GenerateCBinding,GeneratePInvoke */
277 void FindElementsInHostCoordinates_r (Rect p, HitTestCollection *uielement_list);
279 virtual bool CanFindElement () { return false; }
280 virtual void FindElementsInHostCoordinates (cairo_t *cr, Point P, List *uielement_list);
281 virtual void FindElementsInHostCoordinates (cairo_t *cr, Rect r, List *uielement_list);
284 // Recomputes the bounding box, requests redraws,
285 // the parameter determines if we should also update the transformation
287 void FullInvalidate (bool render_xform);
290 // InsideObject:
291 // Returns whether the position x, y is inside the object
293 virtual bool InsideObject (cairo_t *cr, double x, double y);
296 // Checks if the point is inside the Clip region.
297 // Returns true if no Clip region is defined
298 // (which is actually an infinitely big Clip region).
300 bool InsideClip (cairo_t *cr, double x, double y);
303 // Invalidates a subrectangle of this element
305 void Invalidate (Rect r);
308 // Invalidates a subregion of this element
309 void Invalidate (Region *region);
312 // Invalidates the entire bounding rectangle of this element
314 /* @GenerateCBinding */
315 void Invalidate ();
318 // Invalidates the paint region of the element and its subtree
320 void InvalidateSubtreePaint ();
321 void InvalidateMask ();
322 void InvalidateClip ();
323 void InvalidateVisibility ();
326 // GetTransformOrigin:
327 // Returns the transformation origin based on of the item and the
328 // xform_origin
329 virtual Point GetTransformOrigin () {
330 return Point (0, 0);
334 // EmitKeyDown:
336 bool EmitKeyDown (GdkEventKey *key);
339 // EmitKeyUp:
341 bool EmitKeyUp (GdkEventKey *key);
344 // EmitGotFocus:
345 // Invoked when the mouse focuses the given object
347 bool EmitGotFocus ();
350 // EmitLostFocus:
351 // Invoked when the given object loses mouse focus
353 bool EmitLostFocus ();
356 // EmitLostMouseCapture:
357 // Invoked when the given object loses mouse capture
359 bool EmitLostMouseCapture ();
362 // CaptureMouse:
364 // Attempts to capture the mouse. If successful, all mouse
365 // events will be transmitted directly to this element.
366 // Leave/Enter events will no longer be sent.
368 /* @GenerateCBinding,GeneratePInvoke,GenerateJSBinding */
369 bool CaptureMouse ();
370 virtual bool CanCaptureMouse () { return true; }
372 /* @GenerateCBinding,GeneratePInvoke */
373 virtual bool Focus (bool recurse = true);
376 // ReleaseMouseCapture:
378 // Attempts to release the mouse. If successful, any
379 // applicable Leave/Enter events for the current mouse
380 // position will be sent.
382 /* @GenerateCBinding,GeneratePInvoke,GenerateJSBinding */
383 void ReleaseMouseCapture ();
385 virtual int AddHandler (int event_id, EventHandler handler, gpointer data, GDestroyNotify data_dtor = NULL);
386 virtual int RemoveHandler (int event_id, EventHandler handler, gpointer data);
387 virtual void RemoveHandler (int event_id, int token);
389 void WalkTreeForLoadedHandlers (bool *delay, bool only_unemitted, bool force_walk_up);
391 virtual void OnLoaded ();
393 virtual void OnPropertyChanged (PropertyChangedEventArgs *args, MoonError *error);
394 virtual void OnSubPropertyChanged (DependencyProperty *prop, DependencyObject *obj, PropertyChangedEventArgs *subobj_args);
395 virtual void OnCollectionChanged (Collection *col, CollectionChangedEventArgs *args);
398 // CacheInvalidateHint:
399 // Give a hint to this UIElement that it should free any possible
400 // cached (mem-intensive) data it has. This ie. can happen when the
401 // element is removed from a collection, becomes invisible, etc.
403 virtual void CacheInvalidateHint ();
406 // 2.0 methods
409 // Layout foo
411 void DoMeasure ();
412 void DoArrange ();
414 /* @GenerateCBinding,GeneratePInvoke */
415 virtual void Measure (Size availableSize) = 0;
416 /* @GenerateCBinding,GeneratePInvoke */
417 virtual void Arrange (Rect finalRect) = 0;
418 /* @GenerateCBinding,GeneratePInvoke */
419 void InvalidateMeasure ();
420 /* @GenerateCBinding,GeneratePInvoke */
421 void InvalidateArrange ();
422 /* @GenerateCBinding,GeneratePInvoke,GenerateJSBinding */
423 virtual void UpdateLayout () = 0;
425 /* @GenerateCBinding,GeneratePInvoke */
426 Size GetDesiredSize () { return desired_size; }
428 /* @GenerateCBinding,GeneratePInvoke */
429 Size GetRenderSize () { return render_size; }
431 /* @GenerateCBinding,GeneratePInvoke,GenerateJSBinding=TransformToVisual,Version=2.0 */
432 GeneralTransform *GetTransformToUIElementWithError (UIElement *to_element, MoonError *error);
435 // TransformPoint:
437 // Maps the point to the coordinate space of this item
439 void TransformPoint (double *x, double *y);
441 /* @PropertyType=Geometry,GenerateAccessors */
442 const static int ClipProperty;
443 /* @PropertyType=CacheMode,GenerateAccessors */
444 const static int CacheModeProperty;
445 /* @PropertyType=Effect,GenerateAccessors */
446 const static int EffectProperty;
447 /* @PropertyType=Projection,GenerateAccessors */
448 const static int ProjectionProperty;
449 /* @PropertyType=bool,DefaultValue=true,GenerateAccessors */
450 const static int IsHitTestVisibleProperty;
451 /* @PropertyType=Brush,GenerateAccessors */
452 const static int OpacityMaskProperty;
453 /* @PropertyType=double,DefaultValue=1.0,GenerateAccessors */
454 const static int OpacityProperty;
455 /* @PropertyType=Point,DefaultValue=Point (0\,0),GenerateAccessors */
456 const static int RenderTransformOriginProperty;
457 /* @PropertyType=Transform,GenerateAccessors,GenerateManagedAccessors=false */
458 const static int RenderTransformProperty;
459 /* @PropertyType=Visibility,DefaultValue=VisibilityVisible,GenerateAccessors */
460 const static int VisibilityProperty;
461 /* @PropertyType=bool,DefaultValue=true,GenerateAccessors */
462 const static int UseLayoutRoundingProperty;
464 // in 2.0 these properties are actually in FrameworkElement
465 /* @PropertyType=MouseCursor,DefaultValue=MouseCursorDefault,ManagedDeclaringType=FrameworkElement,ManagedPropertyType=Cursor,ManagedFieldAccess=Internal,GenerateAccessors,Validator=CursorValidator */
466 const static int CursorProperty;
467 /* @PropertyType=ResourceDictionary,ManagedDeclaringType=FrameworkElement,AutoCreateValue,ManagedFieldAccess=Internal,GenerateAccessors */
468 const static int ResourcesProperty;
469 /* @PropertyType=object,ManagedDeclaringType=FrameworkElement,ManagedPropertyType=object,IsCustom=true */
470 const static int TagProperty;
471 /* @PropertyType=TriggerCollection,ManagedDeclaringType=FrameworkElement,AutoCreateValue,ManagedFieldAccess=Internal,ManagedSetterAccess=Internal,GenerateAccessors */
472 const static int TriggersProperty;
475 // Property Accessors
478 void SetClip (Geometry *clip);
479 Geometry *GetClip ();
481 void SetCacheMode (CacheMode *mode);
482 CacheMode *GetCacheMode ();
484 MouseCursor GetCursor ();
485 void SetCursor (MouseCursor value);
487 Effect* GetEffect ();
488 void SetEffect (Effect *value);
490 Projection* GetProjection ();
491 void SetProjection (Projection *value);
493 void SetIsHitTestVisible (bool visible);
494 bool GetIsHitTestVisible ();
496 void SetOpacityMask (Brush *mask);
497 Brush *GetOpacityMask ();
499 void SetOpacity (double opacity);
500 double GetOpacity ();
502 void SetRenderTransform (Transform *transform);
503 Transform *GetRenderTransform ();
505 void SetRenderTransformOrigin (Point *origin);
506 Point *GetRenderTransformOrigin ();
508 ResourceDictionary* GetResources();
509 void SetResources (ResourceDictionary *value);
511 TriggerCollection *GetTriggers ();
512 void SetTriggers (TriggerCollection* value);
514 Visibility GetVisibility ();
515 void SetVisibility (Visibility value);
517 bool GetUseLayoutRounding ();
518 void SetUseLayoutRounding (bool value);
520 // Events you can AddHandler to
522 /* @ManagedDeclaringType=FrameworkElement,DelegateType=RoutedEventHandler,GenerateManagedEventField=true */
523 const static int LoadedEvent;
524 /* @DelegateType=MouseEventHandler */
525 const static int MouseMoveEvent;
526 /* @DelegateType=MouseButtonEventHandler,GenerateManagedEventField=true */
527 const static int MouseLeftButtonDownEvent;
528 /* @DelegateType=MouseButtonEventHandler,GenerateManagedEventField=true */
529 const static int MouseLeftButtonUpEvent;
530 /* @DelegateType=KeyEventHandler,GenerateManagedEventField=true */
531 const static int KeyDownEvent;
532 /* @DelegateType=KeyEventHandler,GenerateManagedEventField=true */
533 const static int KeyUpEvent;
534 /* @DelegateType=MouseEventHandler */
535 const static int MouseEnterEvent;
536 /* @DelegateType=MouseEventHandler */
537 const static int MouseLeaveEvent;
538 /* @GenerateManagedEvent=false */
539 const static int InvalidatedEvent;
540 /* @DelegateType=RoutedEventHandler */
541 const static int GotFocusEvent;
542 /* @DelegateType=RoutedEventHandler */
543 const static int LostFocusEvent;
544 /* @DelegateType=MouseEventHandler */
545 const static int LostMouseCaptureEvent;
546 /* @DelegateType=MouseWheelEventHandler */
547 const static int MouseWheelEvent;
549 // these we turn off generation for and handle manually since
550 // they're desktop-only
552 /* @GenerateManagedEvent=false */
553 const static int MouseLeftButtonMultiClickEvent;
554 /* @GenerateManagedEvent=false */
555 const static int MouseRightButtonDownEvent;
556 /* @GenerateManagedEvent=false */
557 const static int MouseRightButtonUpEvent;
559 // Helper method which checks recursively checks this element and its visual
560 // parents to see if any are loaded.
561 static bool IsSubtreeLoaded (UIElement *element);
563 protected:
564 virtual ~UIElement ();
565 Rect IntersectBoundsWithClipPath (Rect bounds, bool transform);
566 void RenderClipPath (cairo_t *cr, bool path_only = false);
568 void SetDesiredSize (Size s) { desired_size = s; }
569 void SetRenderSize (Size s) { render_size = s; }
571 // The computed bounding box
572 Size hidden_desire;
573 Rect bounds;
574 Rect extents;
576 int flags;
578 // Absolute affine transform, precomputed with all of its data
579 cairo_matrix_t absolute_xform;
580 cairo_matrix_t layout_xform;
582 void FrontToBack (Region *surface_region, List *render_list);
583 virtual void PreRender (cairo_t *cr, Region *region, bool front_to_back);
584 virtual void PostRender (cairo_t *cr, Region *region, bool front_to_back);
586 static void CallPreRender (cairo_t *cr, UIElement *element, Region *region, bool front_to_back);
587 static void CallPostRender (cairo_t *cr, UIElement *element, Region *region, bool front_to_back);
589 private:
590 int visual_level;
591 UIElement *visual_parent;
592 DependencyObject *subtree_object;
593 double total_opacity;
594 Brush *opacityMask;
595 Size desired_size;
596 Size render_size;
598 // The local render transform including tranform origin
599 cairo_matrix_t local_xform;
602 #endif /* __MOON_UIELEMENT_H__ */