2009-12-03 Jeffrey Stedfast <fejj@novell.com>
[moon.git] / src / popup.cpp
blob23903a5e657633965715d31412f082bee4878287
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * popup.cpp
5 * Copyright 2009 Novell, Inc. (http://www.novell.com)
7 * See the LICENSE file included with the distribution for details.
8 *
9 */
11 #include "popup.h"
12 #include "runtime.h"
13 #include "deployment.h"
15 Popup::Popup ()
17 SetObjectType (Type::POPUP);
18 shutting_down = false;
19 visible = false;
20 GetDeployment ()->AddHandler (Deployment::ShuttingDownEvent, ShuttingDownCallback, this);
23 void
24 Popup::Dispose ()
26 if (!shutting_down && GetIsOpen ())
27 Hide (GetChild ());
28 GetDeployment ()->RemoveHandler (Deployment::ShuttingDownEvent, ShuttingDownCallback, this);
29 FrameworkElement::Dispose ();
32 void
33 Popup::HitTest (cairo_t *cr, Point p, List *uielement_list)
35 if (visible)
36 FrameworkElement::HitTest (cr, p, uielement_list);
39 void
40 Popup::OnPropertyChanged (PropertyChangedEventArgs *args, MoonError *error)
42 if (args->GetProperty ()->GetOwnerType() != Type::POPUP) {
43 FrameworkElement::OnPropertyChanged (args, error);
44 return;
47 if (args->GetId () == Popup::IsOpenProperty) {
48 // we intentionally don't track whether we've added a tick
49 // call (to make sure we only add it once) for this event
50 // because multiple IsOpen changes cause multiple async events
51 // in SL.
52 if (args->GetNewValue () && args->GetNewValue ()->AsBool ()) {
53 Show (GetChild ());
55 EmitAsync (Popup::OpenedEvent);
57 else {
58 Hide (GetChild ());
60 EmitAsync (Popup::ClosedEvent);
62 } else if (args->GetId () == Popup::ChildProperty) {
63 if (args->GetOldValue () && !args->GetOldValue ()->GetIsNull ()) {
64 FrameworkElement *el = args->GetOldValue ()->AsFrameworkElement ();
65 if (GetIsOpen ())
66 Hide (el);
68 el->SetLogicalParent (NULL, error);
69 if (error->number)
70 return;
72 if (args->GetNewValue () && !args->GetNewValue ()->GetIsNull ()) {
73 FrameworkElement *el = args->GetNewValue ()->AsFrameworkElement ();
74 el->SetLogicalParent (this, error);
75 if (error->number)
76 return;
78 if (GetIsOpen ())
79 Show (el);
81 } else if (args->GetId () == Popup::HorizontalOffsetProperty
82 || args->GetId () == Popup::VerticalOffsetProperty) {
83 UIElement * child = GetChild ();
84 if (child)
85 child->UpdateTransform ();
87 NotifyListenersOfPropertyChange (args, error);
90 void
91 Popup::ShuttingDownHandler (Deployment *sender, EventArgs *args)
93 shutting_down = true;
96 void
97 Popup::Hide (UIElement *child)
99 if (!visible || !child)
100 return;
102 visible = false;
103 Deployment::GetCurrent ()->GetSurface ()->DetachLayer (child);
104 // When the popup is closed, we signal the child that its parent
105 // is enabled as it no longer has any parent
106 PropagateIsEnabledState (child, true);
109 void
110 Popup::Show (UIElement *child)
112 if (visible || !child)
113 return;
115 visible = true;
116 Deployment::GetCurrent ()->GetSurface ()->AttachLayer (child);
117 PropagateIsEnabledState (child, Control::GetParentEnabledState (this));
120 void
121 Popup::PropagateIsEnabledState (UIElement *child, bool enabled_parent)
123 DeepTreeWalker walker (child);
124 while (UIElement *e = walker.Step ()) {
125 if (!e->Is (Type::CONTROL))
126 continue;
128 Control *control = (Control *) e;
129 control->enabled_parent = enabled_parent;
130 control->UpdateEnabled ();
131 walker.SkipBranch ();