public override void SetFocus() { InteractiveComponent firstFocusableItem = Children.Find(delegate(DisplayListMember control) { return(((InteractiveComponent)control).FocusEnabled); }) as InteractiveComponent; //Debug.Log("firstFocusableItem == null: " + (firstFocusableItem == null)); if (null != firstFocusableItem) { firstFocusableItem.SetFocus(); } else { base.SetFocus(); } }
/// <summary> /// Fires when component clicked with a mouse /// The clicked component is obviously mouse enabled /// But not all the clickable components are focusable /// Thus we have to climb up the parent tree to find the first focusable component, or focus routing /// If such component exists, we should set focus on it or run the routing to other component /// </summary> /// <param name="e"></param> private void ComponentMouseDownHandler(Event e) { #if DEBUG if (DebugMode) { Debug.Log("FocusManager: ComponentMouseDownHandler: " + e.Target); } #endif //Debug.Log("FocusManager: ComponentMouseDownHandler: " + e.Target); //((InteractiveComponent)e.Target).SetFocus(); // breaks combobox! //return; InteractiveComponent component = FindFocusableAncestor((InteractiveComponent)e.Target); if (null == component) { return; } if (null != component.FocusRouting) { component.FocusRouting(); return; } if (component == _focusedComponent) { return; } // blur the old one //if (null != _focusedComponent) // commented 20130331 (redundant ?) //{ // Blur(_focusedComponent); //} //Debug.Log("Setting focus on component: " + component); //SetFocus(component); component.SetFocus(); // give the component a chance to handle its focus (pass to child etc.) }
/// <summary> /// Removes a popup from popup stage /// </summary> /// <param name="popup">A popup to remove</param> public void RemovePopup(DisplayObject popup) { #if TRIAL /* HACK CHECK */ Acme acme = (Acme)Framework.GetComponent <Acme>(true); if (null == acme || !acme.gameObject.activeInHierarchy /*active*/ || !acme.enabled) { return; } #endif #if DEBUG if (DebugMode) { Debug.Log("RemovePopup"); } #endif if (!_descriptors.ContainsKey(popup)) { return; } var descriptor = _descriptors[popup]; //if (popup.HasFocus) // FocusManager.Instance.Blur(); if (HasEventListener(CLOSING)) { Event e = new Event(CLOSING, popup, false, true); // cancelable DispatchEvent(e); if (e.Canceled) { return; } } if (IsDefaultPrevented(CLOSING)) { return; } var stage = descriptor.Stage; //Debug.Log(string.Format(@"Removing {0} from {1}", descriptor.PopupRoot, stage)); // removing children //descriptor.PopupRoot.Parent.RemoveChild(descriptor.PopupRoot); stage.RemoveChild(descriptor.PopupRoot); //Debug.Log("Descriptors remove"); _descriptors.Remove(popup); //FocusManager.Instance.Blur(); // TEMP disabled 2.1.2012. _popups.Remove(popup); if (descriptor.FocusPreviousOnHide) { if (_popups.Count > 0) // we have more opened popups { DisplayObject lastPopup = _popups[_popups.Count - 1]; //Debug.Log("_popups.Count: " + _popups.Count); if (lastPopup is InteractiveComponent) { ((InteractiveComponent)lastPopup).SetFocus(); /*lastPopup.Defer(delegate * { * ((InteractiveComponent)lastPopup).SetFocus(); * }, 1);*/ //FocusManager.Instance.SetFocus((InteractiveComponent)lastPopup); } // TEMP disabled on 2.1.2012. because the overlay popup constantly // appears and dissapears and takes focus // and raises "ArgumentException: You can only call GUI functions from inside OnGUI." // should enable back when overlay will be in it's top stage, non run by popup manager } else // this was the only popup { if (popup is Dialog) { Dialog dlg = (Dialog)popup; if (null != dlg.Owner) { // if owner is defined, focus the owner InteractiveComponent ic = dlg.Owner as InteractiveComponent; /*if (null != ic) * ic.SetFocus();*/ if (null != ic) { //((InteractiveComponent)lastPopup).SetFocus(); /*ic.Defer(delegate * { * //ic.SetFocus(); * FocusManager.Instance.SetFocus(ic); * }, 1);*/ //FocusManager.Instance.SetFocus(ic); ic.SetFocus(); } } //else // FocusManager.Instance.Blur(); // else blur everything // commented 20130331 - because after closing th eallert, the SetFocus te TextField (via the callback) didn't work } } } // disconnect if (_descriptors.Count == 0) { SystemManager.Instance.ResizeSignal.Disconnect(ResizeSlot); SystemManager.Instance.MouseDownSignal.Disconnect(MouseDownSlot); SystemManager.Instance.MouseWheelSignal.Disconnect(MouseWheelSlot); stage.RemoveEventListener(MouseEvent.MOUSE_DOWN, MouseDownHandler); } //Debug.Log("_descriptors.Count: " + _descriptors.Count); //_stage.ValidateNow(); if (HasEventListener(CLOSE)) { DispatchEvent(new Event(CLOSE, popup)); } if (descriptor.Popup != descriptor.PopupRoot) { // this is a modal popup // the removed effect won't play on popup, because PopupRoot is being removed, not the popup // we have to handle this case and play the effect here Component component = popup as Component; if (null != component && component.HasStyle("removedEffect")) { ITweenFactory removeEffect = (ITweenFactory)component.GetStyle("removedEffect"); removeEffect.Play(popup); } } }
//private void RemoveHandler(Event e) //{ // DisplayObject popup = e.Target as DisplayObject; // if (null != popup) // { // popup.RemoveEventListener(MouseEvent.MOUSE_DOWN_OUTSIDE, RemoveHandler); // popup.RemoveEventListener(MouseEvent.MOUSE_WHEEL_OUTSIDE, RemoveHandler); // TerminatePopup(popup); // } // if (_popups.Count == 0 && SystemManager.Instance.HasEventListener(ResizeEvent.RESIZE)) // SystemManager.Instance.RemoveEventListener(ResizeEvent.RESIZE, RemoveHandler); //} //private static void TerminatePopup(DisplayObject popup) //{ // //Debug.Log("TerminatePopup"); // var dlm = popup as DisplayListMember; // if (null != dlm) // { // Instance.RemovePopup(dlm); // // TODO: SystemManager.Instance.RemoveEventListener(ResizeEvent.RESIZE, ...); // dlm.Dispose(); // } //} #endregion #region Add /// <summary> /// Adds a popup to popup stage /// </summary> /// <param name="popup">A popup to add</param> /// <param name="options">Popup options</param> public void AddPopup(DisplayListMember popup, params PopupOption[] options) { Event e = new Event(OPENING, popup, false, true); // cancelable DispatchEvent(e); if (e.Canceled) { return; } if (IsDefaultPrevented(OPENING)) { return; } if (_popups.Contains(popup)) { return; } #if DEBUG if (DebugMode) { Debug.Log("AddPopup"); } #endif DisplayObjectContainer parent = null; bool modal = true; bool centered = true; bool keepCenter = false; bool removeOnMouseDownOutside = false; bool removeOnMouseWheelOutside = false; bool removeOnScreenResize = false; bool autoFocus = true; bool focusPreviousOnHide = true; Stage stage = _stage; bool visibleFlag = popup.Visible; popup.Visible = false; int len = options.Length; for (int i = 0; i < len; i++) { PopupOption option = options[i]; switch (option.Type) { case PopupOptionType.Parent: parent = (DisplayObjectContainer)option.Value; break; case PopupOptionType.Modal: modal = (bool)option.Value; break; case PopupOptionType.Centered: centered = (bool)option.Value; break; case PopupOptionType.KeepCenter: keepCenter = (bool)option.Value; break; case PopupOptionType.RemoveOnMouseDownOutside: removeOnMouseDownOutside = (bool)option.Value; break; case PopupOptionType.RemoveOnMouseWheelOutside: removeOnMouseWheelOutside = (bool)option.Value; break; case PopupOptionType.RemoveOnScreenResize: removeOnScreenResize = (bool)option.Value; break; case PopupOptionType.AutoFocus: autoFocus = (bool)option.Value; break; case PopupOptionType.FocusPreviousOnHide: focusPreviousOnHide = (bool)option.Value; break; case PopupOptionType.Stage: //Debug.Log("Exotic stage: " + option.Value); stage = (Stage)option.Value; break; default: throw new Exception("Unknown option"); } } _popups.Add(popup); if (null == parent) { parent = stage; } DisplayListMember overlay = null; Group popupRoot = null; InvalidationManagerClient imc = popup as InvalidationManagerClient; Component comp = popup as Component; if (null != comp) { comp.IsPopUp = true; } if (modal) { overlay = (DisplayListMember)Activator.CreateInstance(ModalOverlayType); overlay.AddEventListener(MouseEvent.MOUSE_DOWN, OnOverlayMouseDown); // we are packing both the overlay and the popup to into an aditional container popupRoot = new Group(); stage.AddChild(popupRoot); // BUG BUG BUG! If we do _stage.AddChild(popupRoot); AFTER the children are added, we get a null exception // this is the major problem when adding children, started appearing since 10.1.2012 // solved. This had to to with the creationcomplete method, which has to be run after the complete invalidation pass popupRoot.AddChild(overlay); popupRoot.AddChild(popup); // popup has been added to popup stage // invalidation methods have been called upon the addition // now we want to run measure (to validate dimensions) // because we want to center the popup // now, the absolute layout won't do it on his own //overlay.Bounds = (Rectangle)parent.Bounds.Clone(); overlay.Width = PopupManagerStage.Instance.Width; overlay.Height = PopupManagerStage.Instance.Height; /*var client = overlay as InvalidationManagerClient; * if (client != null) * { * /*var imc2 = client; * imc2.SetActualSize( * PopupManagerStage.Instance.Width, * PopupManagerStage.Instance.Height/*, * Math.Max(imc2.GetExplicitOrMeasuredWidth(), imc2.MinWidth), * Math.Max(imc2.GetExplicitOrMeasuredHeight(), imc2.MinHeight)#2# * );#1# * client.Width = PopupManagerStage.Instance.Width; * client.Height = PopupManagerStage.Instance.Height; * //imc2.InvalidateTransform(); * } * else * { * overlay.X = parent.X; * overlay.Y = parent.Y; * /*overlay.X = parent.X; * overlay.Y = parent.Y;#1# * }*/ } else { stage.AddChild(popup); } if (null != imc) { //InvalidationManager.Instance.ValidateClient(imc, true); imc.ValidateNow(); //Debug.Log(string.Format("imc.Width:{0}, imc.Height:{1}", imc.Width, imc.Height)); //Debug.Log(string.Format("imc.GetExplicitOrMeasuredWidth():{0}, imc.GetExplicitOrMeasuredHeight():{1}", imc.GetExplicitOrMeasuredWidth(), imc.GetExplicitOrMeasuredHeight())); //imc.SetActualSize(imc.GetExplicitOrMeasuredWidth(), imc.GetExplicitOrMeasuredHeight()); imc.SetActualSize( Math.Min(Math.Max(imc.GetExplicitOrMeasuredWidth(), imc.MinWidth), imc.MaxWidth), Math.Min(Math.Max(imc.GetExplicitOrMeasuredHeight(), imc.MinHeight), imc.MaxHeight) ); } var descriptor = new PopupDescriptor(parent, overlay, popupRoot) { Popup = popup, PopupRoot = modal ? popupRoot : popup, Owner = parent, Modal = modal, Centered = centered, KeepCenter = keepCenter, RemoveOnMouseDownOutside = removeOnMouseDownOutside, RemoveOnMouseWheelOutside = removeOnMouseWheelOutside, RemoveOnScreenResize = removeOnScreenResize, FocusPreviousOnHide = focusPreviousOnHide, Stage = stage }; _descriptors.Add(popup, descriptor); if (centered) { CenterPopUp(popup); } InteractiveComponent ic = popup as InteractiveComponent; if (autoFocus && null != ic) { ic.SetFocus(); // TEMP disabled, 2.1.2012. //FocusManager.Instance.SetFocus(ic); /*ic.Defer(delegate * { * //ic.SetFocus(); * FocusManager.Instance.SetFocus(ic); * }, 1);*/ } // connect if not connected if (_descriptors.Count > 0) { SystemManager.Instance.ResizeSignal.Connect(ResizeSlot); SystemManager.Instance.MouseDownSignal.Connect(MouseDownSlot); SystemManager.Instance.RightMouseDownSignal.Connect(MouseDownSlot); SystemManager.Instance.MiddleMouseDownSignal.Connect(MouseDownSlot); SystemManager.Instance.MouseWheelSignal.Connect(MouseWheelSlot); // subscribe to stage to see if some component has been mouse-downed // NOTE: some components (i.e. window close button) could cancel the event, this is by design // note: it is safe ta call it multiple times, it is checked internally stage.AddEventListener(MouseEvent.MOUSE_DOWN, MouseDownHandler); } else { SystemManager.Instance.ResizeSignal.Disconnect(ResizeSlot); SystemManager.Instance.MouseDownSignal.Disconnect(MouseDownSlot); SystemManager.Instance.RightMouseDownSignal.Disconnect(MouseDownSlot); SystemManager.Instance.MiddleMouseDownSignal.Disconnect(MouseDownSlot); SystemManager.Instance.MouseWheelSignal.Disconnect(MouseWheelSlot); //MouseEventDispatcher.Instance.RemoveEventListener(MouseEvent.MOUSE_DOWN, MouseDownHandler); stage.RemoveEventListener(MouseEvent.MOUSE_DOWN, MouseDownHandler); } // NOTE: This is needed when having effects because of the flicker (?): //descriptor.PopupRoot.SkipRender(100); // bring the popup root to front descriptor.PopupRoot.BringToFront(); popup.Visible = visibleFlag; DispatchEvent(new Event(OPEN, popup)); }
private void KeyDownHandler(Event e) { KeyboardEvent ke = (KeyboardEvent)e; int index = _components.IndexOf(FocusManager.Instance.FocusedComponent); if (-1 == index) { return; } bool keyRecognized = false; switch (ke.KeyCode) { case KeyCode.Tab: //Debug.Log("Tab"); keyRecognized = true; index = ke.Shift ? Previous(index, _circularTabs ?? false) : Next(index, _circularTabs ?? false); break; case KeyCode.LeftArrow: //Debug.Log("LeftArrow"); if (_arrowsEnabled) { keyRecognized = true; index = Previous(index, _circularTabs ?? false); } break; case KeyCode.RightArrow: //Debug.Log("CircularArrows: " + CircularArrows); if (_arrowsEnabled) { keyRecognized = true; index = Next(index, _circularTabs ?? false); } break; case KeyCode.UpArrow: //Debug.Log("LeftArrow"); if (_arrowsEnabled && _upDownArrowsEnabled) { keyRecognized = true; index = Previous(index, _circularTabs ?? false); } break; case KeyCode.DownArrow: //Debug.Log("CircularArrows: " + CircularArrows); if (_arrowsEnabled && _upDownArrowsEnabled) { keyRecognized = true; index = Next(index, _circularTabs ?? false); } break; default: break; } if (keyRecognized) { /** * Important: canceling the event alters with behavours of container children !!! * (for instance, TabManager set on Form swallows the key events needed by combo box) * */ e.CancelAndStopPropagation(); InteractiveComponent componentToFocus = _components[index] as InteractiveComponent; if (null != componentToFocus) { if (!componentToFocus.FocusEnabled) { #if DEBUG if (DebugMode) { Debug.Log("Component is not focus enabled: " + componentToFocus); return; } #endif } #if DEBUG if (DebugMode) { Debug.Log("Focusing component: " + componentToFocus); } #endif FocusManager.Instance.TabbedToFocus = true; componentToFocus.SetFocus(); } else { #if DEBUG if (DebugMode) { Debug.LogWarning("Component to focus not instantiated"); } #endif } } }