Exemple #1
0
        public override void OnRender(Renderman renderer)
        {
            // Get the target:
            HtmlElement target = ScrollBar.scrollTarget;

            if (target == null)
            {
                return;
            }

            ComputedStyle computed = target.style.Computed;
            LayoutBox     box      = computed.FirstBox;

            if (box == null)
            {
                // Not visible or hasn't been drawn yet.
                return;
            }

            int   overflowMode = IsVertical?box.OverflowY : box.OverflowX;
            float visible      = IsVertical?box.VisiblePercentageY() : box.VisiblePercentageX();

            if (visible > 1f)
            {
                visible = 1f;
            }
            else if (visible < 0f)
            {
                visible = 0f;
            }

            // Handle auto next:
            if (overflowMode == VisibilityMode.Auto && visible == 1f)
            {
                // Hide it:
                ScrollBar.Style.display = "none";

                // Make sure it's not scrolled:
                if (IsVertical && box.Scroll.Top != 0f)
                {
                    if (box.Scroll.Top != 0f)
                    {
                        // Clear it:
                        computed.ChangeTagProperty("scroll-top", new Css.Units.DecimalUnit(0f));
                    }
                }
                else if (box.Scroll.Left != 0f)
                {
                    computed.ChangeTagProperty("scroll-left", new Css.Units.DecimalUnit(0f));
                }

                // Mark as hidden so the informer can watch out for it:
                ScrollBar.Hidden = true;

                return;
            }

            ApplyTabSize(visible, Style.Computed.FirstBox);
        }
Exemple #2
0
        public override void OnClickEvent(MouseEvent clickEvent)
        {
            if (Details == null)
            {
                return;
            }

            // Hide/show the details element.

            // Grab the details computed style:
            ComputedStyle computed = Details.Style.Computed;

            // The display it's going to:
            string display;

            // Is it currently visible?
            if (computed.DisplayX == DisplayMode.None)
            {
                // Nope! Show it.
                display = "block";
            }
            else
            {
                // Yep - hide it.
                display = "none";
            }

            // Change its display:
            computed.ChangeTagProperty("display", display);
        }
Exemple #3
0
        public override bool OnAttributeChange(string property)
        {
            if (base.OnAttributeChange(property))
            {
                return(true);
            }

            ComputedStyle computed = Style.Computed;

            string value = getAttribute(property);

            if (value == null)
            {
                value = "";
            }

            if (property == "color")
            {
                Style.Computed.ChangeTagProperty(
                    "color",
                    new Css.Units.ColourUnit(
                        Css.ColourMap.ToSpecialColour(getAttribute("color"))
                        )
                    );
            }
            else if (property == "size")
            {
                if (value != "")
                {
                    value += "px";
                }
                computed.ChangeTagProperty("font-size", value);
            }
            else if (property == "face")
            {
                computed.ChangeTagProperty("font-family", value);
            }
            else
            {
                return(false);
            }

            return(true);
        }
        public override void OnLoaded(string type)
        {
            ComputedStyle computed = Element.Style.Computed;

            if (computed.BGImage == null)
            {
                return;
            }

            Image = computed.BGImage.Image;

            if (Image == null)
            {
                return;
            }

            float width  = (float)Image.Width();
            float height = (float)Image.Height();

            // Figure out the aspect ratios:
            AspectRatio        = width / height;
            InverseAspectRatio = height / width;

            if (Image.PixelPerfect)
            {
                width  *= ScreenInfo.ResolutionScale;
                height *= ScreenInfo.ResolutionScale;
            }

            // Compute the tag width:
            TagWidth = new Css.Value((int)width + "fpx", Css.ValueType.Pixels);

            // Compute the tag height:
            TagHeight = new Css.Value((int)height + "fpx", Css.ValueType.Pixels);

            // Act like we're setting tag properties:
            // This is so that class/ID/Style can override any of them.
            computed.ChangeTagProperty("height", TagHeight);
            computed.ChangeTagProperty("width", TagWidth);
            computed.ChangeTagProperty("background-repeat", new Css.Value("no-repeat", Css.ValueType.Text));
            computed.ChangeTagProperty("background-size", new Css.Value("100% 100%", Css.ValueType.Point));
        }
        public override bool OnAttributeChange(string property)
        {
            if (base.OnAttributeChange(property))
            {
                return(true);
            }

            ComputedStyle computed = Element.Style.Computed;

            string value = Element[property];

            if (value == null)
            {
                value = "";
            }

            if (property == "color")
            {
                computed.ChangeTagProperty("color", new Css.Value(value, Css.ValueType.Color));
            }
            else if (property == "size")
            {
                if (value != "")
                {
                    value += "px";
                }
                computed.ChangeTagProperty("font-size", new Css.Value(value));
            }
            else if (property == "face")
            {
                computed.ChangeTagProperty("font-family", new Css.Value(value, Css.ValueType.Text));
            }
            else
            {
                return(false);
            }

            return(true);
        }
Exemple #6
0
        /// <summary>Scrolls the input box if the given position is out of bounds.</summary>
        private void ScrollIfBeyond(ref Vector2 position)
        {
            // Scroll input if the caret is beyond the end of the box:
            ComputedStyle inputCS = Input.Style.Computed;

            LayoutBox input = inputCS.FirstBox;

            float boxSize    = input.InnerWidth;
            float scrollLeft = input.Scroll.Left;

            float scrolledPosition = position.x - scrollLeft;

            if (scrolledPosition > boxSize)
            {
                // Beyond the right edge.
                // Scroll it such that the caret is positioned just on that right edge:
                scrollLeft += (scrolledPosition - boxSize) + 3f;
            }
            else if (scrolledPosition < 0f)
            {
                // Beyond the left edge.
                // Scroll it such that the caret is positioned just on that left edge:
                scrollLeft += scrolledPosition;
            }

            // Clamp the scrolling:
            if (scrollLeft < 0f)
            {
                scrollLeft = 0f;
            }

            // Update scroll left:
            if (scrollLeft != input.Scroll.Left)
            {
                // For this pass:
                input.Scroll.Left = scrollLeft;

                // For future passes:
                inputCS.ChangeTagProperty("scroll-left", new Css.Units.DecimalUnit(scrollLeft), false);
            }
        }
        public override bool OnAttributeChange(string property)
        {
            if (base.OnAttributeChange(property))
            {
                return(true);
            }

            if (property == "src")
            {
                string src = Element["src"];

                if (src == null)
                {
                    src = "";
                }

                ComputedStyle computed = Element.Style.Computed;
                computed.ChangeTagProperty("background-image", new Css.Value(src, Css.ValueType.Text));
                return(true);
            }
            return(false);
        }
Exemple #8
0
        public override bool OnClick(UIEvent clickEvent)
        {
            base.OnClick(clickEvent);

            if (Details == null)
            {
                return(false);
            }

            if (!clickEvent.heldDown)
            {
                // Hide/show the details element.

                // Grab the details computed style:
                ComputedStyle computed = Details.Style.Computed;

                // The display it's going to:
                string display;

                // Is it currently visible?
                if (computed.Display == DisplayType.None)
                {
                    // Nope! Show it.
                    display = "block";
                }
                else
                {
                    // Yep - hide it.
                    display = "none";
                }

                // Change it's display:
                computed.ChangeTagProperty("display", new Css.Value(display, Css.ValueType.Text));
            }

            return(true);
        }
Exemple #9
0
        public override bool OnAttributeChange(string property)
        {
            if (base.OnAttributeChange(property))
            {
                return(true);
            }

            if (property == "dir")
            {
                // Grab the direction:
                string direction = getAttribute("dir");

                // Grab the computed style:
                ComputedStyle computed = Style.Computed;

                // Apply it to CSS - it's exactly the same value for the direction CSS property:
                computed.ChangeTagProperty("direction", direction);

                return(true);
            }


            return(false);
        }
Exemple #10
0
        public override bool OnAttributeChange(string property)
        {
            if (base.OnAttributeChange(property))
            {
                return(true);
            }

            if (property == "dir")
            {
                // Grab the direction:
                string direction = Element["dir"];

                // Grab the computed style:
                ComputedStyle computed = Element.style.Computed;

                // Apply it to CSS - it's exactly the same value for the direction CSS property:
                computed.ChangeTagProperty("direction", new Css.Value(direction, Css.ValueType.Text));

                return(true);
            }


            return(false);
        }
Exemple #11
0
        /// <summary>Scrolls this scrollbar by the given number of pixels, optionally relative to a fixed point on the bar.
        /// Note that this may fail if the scrollbar cannot scroll any further.</summary>
        /// <param name="pixels">The number of pixels to scroll this bar by.</param>
        /// <param name="fromCurrent">True if pixels is relative to where the thumb currently is. False if pixels is relative
        /// to where the bar was when the mouse was clicked. See e.g. <see cref="PowerUI.VScrollTabTag.StartY"/>.</param>
        /// <param name="scrollTarget">True if the target should also be scrolled.</param>
        public void ScrollBy(float pixels, bool fromCurrent, bool scrollTarget)
        {
            // Scroll it by pixels from Start.
            float newLocation     = pixels;
            float currentPosition = Position;

            LayoutBox box = RenderData.FirstBox;

            if (fromCurrent)
            {
                newLocation += currentPosition;
            }
            else
            {
                newLocation += Start;
            }

            // Get the size of the button before the tab:
            float sizeBefore = StartArrowSize;

            float barSize = BarSize;

            float max = barSize + sizeBefore;

            if (IsVertical)
            {
                max -= box.Height;
            }
            else
            {
                max -= box.Width;
            }

            if (newLocation < sizeBefore)
            {
                newLocation = sizeBefore;
            }
            else if (newLocation > max)
            {
                newLocation = max;
            }

            if (newLocation == currentPosition)
            {
                return;
            }

            if (IsVertical)
            {
                Style.top = newLocation + "fpx";
            }
            else
            {
                Style.left = newLocation + "fpx";
            }

            // Fire a change event on the scrollbar:
            Dom.Event e = new Dom.Event("change");
            e.SetTrusted();
            ScrollBar.dispatchEvent(e);

            if (scrollTarget)
            {
                // Get info for the target:
                HtmlElement   target   = ScrollBar.scrollTarget;
                ComputedStyle targetCs = target.style.Computed;
                box = targetCs.FirstBox;

                if (target != null && box != null)
                {
                    // Get the progress:
                    float progress = (newLocation - sizeBefore) / barSize;

                    // Update CSS:
                    if (IsVertical)
                    {
                        targetCs.ChangeTagProperty("scroll-top", new Css.Units.DecimalUnit(progress * box.ContentHeight));
                    }
                    else
                    {
                        targetCs.ChangeTagProperty("scroll-left", new Css.Units.DecimalUnit(progress * box.ContentWidth));
                    }

                    // And request a redraw:
                    target.htmlDocument.RequestLayout();
                }
            }
        }
Exemple #12
0
		/// <summary>Updates mouse overs, touches and the mouse position.</summary>
		public static void Update(){
			
			InputPointer pointer;
			
			// Look out for any 'new' touch events:
			int touchCount=UnityEngine.Input.touchCount;
			
			if(touchCount>0){
				
				// For each one..
				for(int i=0;i<touchCount;i++){
					
					// Get the info:
					Touch touch=UnityEngine.Input.GetTouch(i);
					
					pointer=null;
					
					// Already seen this one?
					// There won't be many touches so a straight linear scan is by far the fastest option here.
					// (It's much better than a dictionary).
					for(int p=InputPointer.PointerCount-1;p>=0;p--){
						
						// Get the pointer:
						InputPointer current=InputPointer.AllRaw[p];
						
						if(current.ID==touch.fingerId){
							
							// Got it!
							pointer=current;
							break;
							
						}
						
					}
					
					TouchPointer tp=null;
					
					if(pointer==null){
						
						// Touch start! A new finger has been seen for the first time.
						#if UNITY_5_3_OR_NEWER
							
							// Could be a stylus:
							if(touch.type==TouchType.Stylus){
								tp=new StylusPointer();
							}else{
								tp=new FingerPointer();
							}
							
						#else
							
							// Can only assume it's a finger here:
							tp=new FingerPointer();
						
						#endif
						
						// Add it to the available set:
						tp.ID=touch.fingerId;
						tp.Add();
						
					}else{
						
						// Apply latest info:
						tp=(pointer as TouchPointer);
						
					}
					
					// Mark it as still alive so it doesn't get removed shortly.
					tp.StillAlive=true;
					tp.LatestPosition=touch.position;
					
					#if UNITY_5_3_OR_NEWER
					
					tp.Radius=touch.radius;
					tp.RadiusVariance=touch.radiusVariance;
					tp.LatestPressure=touch.pressure;
					
					// Is it a stylus?
					if(tp is StylusPointer){
						tp.UpdateStylus(touch.azimuthAngle,touch.altitudeAngle);
					}
					
					// Always a pressure of 1 otherwise (the default).
					#endif
				}
				
			}
			
			// Update each pointer, invalidating itself only if it has moved:
			bool pointerRemoved=false;
			
			for(int i=InputPointer.PointerCount-1;i>=0;i--){
				
				// Get the pointer:
				pointer=InputPointer.AllRaw[i];
				
				// Update its position and state now:
				Vector2 delta;
				bool moved=pointer.Relocate(out delta);
				
				if(pointer.Removed){
					// It got removed! (E.g. a finger left the screen).
					pointerRemoved=true;
					
					// Clear pressure (mouseup etc):
					pointer.SetPressure(0f);
					
					if(pointer.ActiveOverTarget!=null){
						
						// Shared event:
						MouseEvent mouseEvent=new MouseEvent(pointer.ScreenX,pointer.ScreenY,pointer.ButtonID,false);
						mouseEvent.trigger=pointer;
						mouseEvent.clientX=pointer.DocumentX;
						mouseEvent.clientY=pointer.DocumentY;
						mouseEvent.SetModifiers();
						mouseEvent.SetTrusted();
						
						// Trigger a mouseout (bubbles):
						mouseEvent.EventType="mouseout";
						mouseEvent.SetTrusted();
						pointer.ActiveOverTarget.dispatchEvent(mouseEvent);
						
						// And a mouseleave (doesn't bubble).
						mouseEvent.Reset();
						mouseEvent.bubbles=false;
						mouseEvent.EventType="mouseleave";
						pointer.ActiveOverTarget.dispatchEvent(mouseEvent);
						
						// Update the CSS (hover; typically out):
						IRenderableNode irn = (pointer.ActiveOverTarget as IRenderableNode);
						
						if(irn!=null){
							irn.ComputedStyle.RefreshLocal(true);
						}
						
					}
					
					continue;
				}
				
				// If the pointer is invalid or they all are:
				if(moved || PointersInvalid){
					
					// Figure out what's under it. This takes its pos on the screen
					// and figures out what's there, as well as converting the position
					// to one which is relative to the document (used by e.g. a WorldUI).
					float documentX=pointer.ScreenX;
					float documentY=pointer.ScreenY;
					EventTarget newActiveOver=TargetFromPoint(ref documentX,ref documentY,pointer);
					
					// Update docX/Y:
					pointer.DocumentX=documentX;
					pointer.DocumentY=documentY;
					
					// Get the old one:
					EventTarget oldActiveOver=pointer.ActiveOverTarget;
					
					// Shared event:
					MouseEvent mouseEvent=new MouseEvent(documentX,documentY,pointer.ButtonID,pointer.IsDown);
					mouseEvent.trigger=pointer;
					mouseEvent.clientX=pointer.DocumentX;
					mouseEvent.clientY=pointer.DocumentY;
					mouseEvent.SetModifiers();
					mouseEvent.SetTrusted();
					
					// If overElement has changed from the previous one..
					if(newActiveOver!=oldActiveOver){
						
						if(oldActiveOver!=null){
							
							// Trigger a mouseout (bubbles):
							mouseEvent.EventType="mouseout";
							mouseEvent.SetTrusted();
							mouseEvent.relatedTarget=newActiveOver;
							oldActiveOver.dispatchEvent(mouseEvent);
							
							// And a mouseleave (doesn't bubble).
							// Only triggered if newActiveOver is *not* the parent of oldActiveOver.
							if(oldActiveOver.eventTargetParentNode!=newActiveOver){
								mouseEvent.Reset();
								mouseEvent.bubbles=false;
								mouseEvent.EventType="mouseleave";
								mouseEvent.relatedTarget=newActiveOver;
								oldActiveOver.dispatchEvent(mouseEvent);
							}
							
						}
						
						// Update it:
						pointer.ActiveOverTarget=newActiveOver;
						
						if(oldActiveOver!=null){
							// Update the CSS (hover; typically out):
							IRenderableNode irn = (oldActiveOver as IRenderableNode);
							
							if(irn!=null){
								irn.ComputedStyle.RefreshLocal(true);
							}
						}
						
						if(newActiveOver!=null){
							// Update the CSS (hover; typically in)
							IRenderableNode irn = (newActiveOver as IRenderableNode);
							
							if(irn!=null){
								irn.ComputedStyle.RefreshLocal(true);
							}
						}
						
						// Trigger a mouseover (bubbles):
						mouseEvent.Reset();
						mouseEvent.bubbles=true;
						mouseEvent.relatedTarget=oldActiveOver;
						mouseEvent.EventType="mouseover";
						
						if(newActiveOver==null){
							
							// Clear the main UI tooltip:
							UI.document.tooltip=null;
							
							// Dispatch to unhandled:
							Unhandled.dispatchEvent(mouseEvent);
							
						}else{
							
							newActiveOver.dispatchEvent(mouseEvent);
							
							// Set the tooltip if we've got one:
							UI.document.tooltip=newActiveOver.getTitle();
							
							// And a mouseenter (doesn't bubble).
							// Only triggered if newActiveOver is *not* a child of oldActiveOver.
							if(newActiveOver.eventTargetParentNode!=oldActiveOver){
								mouseEvent.Reset();
								mouseEvent.bubbles=false;
								mouseEvent.EventType="mouseenter";
								mouseEvent.relatedTarget=oldActiveOver;
								newActiveOver.dispatchEvent(mouseEvent);
							}
							
						}
						
					}
					
					if(moved){
						
						// Trigger a mousemove event:
						mouseEvent.Reset();
						mouseEvent.bubbles=true;
						mouseEvent.EventType="mousemove";
						
						if(newActiveOver==null){
							Unhandled.dispatchEvent(mouseEvent);
						}else{
							newActiveOver.dispatchEvent(mouseEvent);
						}
						
					}
					
				}
				
				// If the pointer requires pressure changes..
				if(pointer.FireTouchEvents){
					
					// Set the pressure (which triggers mousedown/up for us too):
					TouchPointer tp=(pointer as TouchPointer);
					
					tp.SetPressure(tp.LatestPressure);
					
					// We test touch move down here because it must happen after we've
					// transferred 'ActiveOver' to 'ActiveDown' which happens inside SetPressure.
					
					// Touch events are triggered on the element that was pressed down on
					// (even if we've moved beyond it's bounds).
					if(moved){
						
						// Trigger a touchmove event too:
						TouchEvent te=new TouchEvent("touchmove");
						te.trigger=pointer;
						te.SetTrusted();
						te.clientX=pointer.DocumentX;
						te.clientY=pointer.DocumentY;
						te.SetModifiers();
						
						if(pointer.ActivePressedTarget==null){
							
							// Trigger on unhandled:
							Unhandled.dispatchEvent(te);
							
						}else{
						
							pointer.ActivePressedTarget.dispatchEvent(te);
						
						}
						
					}
					
				}
				
				// Test for dragstart
				if(pointer.IsDown && moved){
					
					// How far has it moved since it went down?
					if(pointer.DragStatus==InputPointer.DRAG_UNKNOWN){
						
						// Is the element we pressed (or any of its parents) draggable?
						if(pointer.MinDragDistance==0f){
							
							// Find if we've got a draggable element:
							pointer.ActiveUpdatingTarget=GetDraggable(pointer.ActivePressedTarget as Element);
							
							// Find the min drag distance:
							pointer.MinDragDistance=pointer.GetMinDragDistance();
							
						}
						
						if(pointer.MovedBeyondDragDistance){
							
							// Possibly dragging.
							
							// Actually marked as 'draggable'?
							if(pointer.ActiveUpdatingTarget!=null){
								
								// Try start drag:
								DragEvent de=new DragEvent("dragstart");
								de.trigger=pointer;
								de.SetModifiers();
								de.SetTrusted();
								de.deltaX=delta.x;
								de.deltaY=delta.y;
								de.clientX=pointer.DocumentX;
								de.clientY=pointer.DocumentY;
								
								if(pointer.ActivePressedTarget.dispatchEvent(de)){
									
									// We're now dragging!
									pointer.DragStatus=InputPointer.DRAGGING;
									
								}else{
									
									// It didn't allow it. This status prevents it from spamming dragstart.
									pointer.DragStatus=InputPointer.DRAG_NOT_AVAILABLE;
									
								}
								
							}else{
								
								// Selectable?
								IRenderableNode irn = (pointer.ActivePressedTarget as IRenderableNode);
								
								if(irn!=null){
									// It's renderable; can it be selected?
									ComputedStyle cs=irn.ComputedStyle;
									Css.Value userSelect=cs[Css.Properties.UserSelect.GlobalProperty];
									
									if(userSelect!=null && !(userSelect.IsType(typeof(Css.Keywords.None))) && !userSelect.IsAuto){
										
										// Selectable!
										Css.Properties.UserSelect.BeginSelect(pointer,userSelect);
										
										// Set status:
										pointer.DragStatus=InputPointer.SELECTING;
										
										// Focus it if needed:
										HtmlElement html=(pointer.ActivePressedTarget as HtmlElement);
										
										if(html!=null){
											html.focus();
										}
										
									}else{
										
										// This status prevents it from spamming, at least until we release.
										pointer.DragStatus=InputPointer.DRAG_NOT_AVAILABLE;
										
									}
								
								}
								
							}
							
						}
						
					}else if(pointer.DragStatus==InputPointer.DRAGGING){
						
						// Move the dragged element (the event goes to everybody):
						if(pointer.ActivePressedTarget!=null){
							
							DragEvent de=new DragEvent("drag");
							de.trigger=pointer;
							de.SetModifiers();
							de.SetTrusted();
							de.deltaX=delta.x;
							de.deltaY=delta.y;
							de.clientX=pointer.DocumentX;
							de.clientY=pointer.DocumentY;
							
							if(pointer.ActivePressedTarget.dispatchEvent(de)){
								
								// Note that onDrag runs on the *dragging* element only.
								Element dragging;
								
								if(pointer.ActiveUpdatingTarget==null){
									dragging = (Element)pointer.ActivePressedTarget;
								}else{
									dragging = (Element)pointer.ActiveUpdatingTarget;
								}
								
								if(dragging.OnDrag(de)){
									
									// Run the PowerUI default - move the element:
									RenderableData renderData=(dragging as IRenderableNode).RenderData;
									
									// Get the "actual" left/top values:
									if(renderData.FirstBox!=null){
										
										// Get computed style:
										ComputedStyle cs=renderData.computedStyle;
										
										// Fix if it isn't already:
										if(renderData.FirstBox.PositionMode!=PositionMode.Fixed){
											
											cs.ChangeTagProperty("position","fixed");
											
										}
										
										// Get top/left pos:
										float left=renderData.FirstBox.X+delta.x;
										float top=renderData.FirstBox.Y+delta.y;
										
										// Write it back out:
										cs.ChangeTagProperty("left",new Css.Units.DecimalUnit(left));
										cs.ChangeTagProperty("top",new Css.Units.DecimalUnit(top));
										
									}
									
								}
							}
							
						}
						
					}else if(pointer.DragStatus==InputPointer.SELECTING){
						
						// Update the selection.
						
						if(pointer.ActivePressedTarget!=null){
							
							DragEvent de=new DragEvent("drag");
							de.trigger=pointer;
							de.SetModifiers();
							de.SetTrusted();
							de.clientX=pointer.DocumentX;
							de.clientY=pointer.DocumentY;
							
							if(pointer.ActivePressedTarget.dispatchEvent(de)){
								
								// We can only select elements:
								Element pressedElement = (Element)pointer.ActivePressedTarget;
								
								// Get the current selection:
								Selection s=(pressedElement.document as HtmlDocument).getSelection();
								
								// Safety check:
								if(s.ranges.Count>0){
									
									// Get the range:
									Range range=s.ranges[0];
									
									// Get text node:
									RenderableTextNode htn=(range.startContainer as RenderableTextNode);
									
									if(htn!=null){
										
										// Get the new end index:
										int endIndex=htn.LetterIndex(pointer.DocumentX,pointer.DocumentY);
										
										// Update:
										range.endOffset=endIndex;
										
										// Flush:
										s.UpdateSelection(true,range);
										
									}
									
								}
								
							}
							
						}
						
					}
					
				}
				
			}
			
			if(pointerRemoved){
				// Tidy the removed ones:
				InputPointer.Tidy();
			}
			
			// Clear invalidated state:
			PointersInvalid=false;
			
			#if MOBILE
			// Handle mobile keyboard:
			if(MobileKeyboard!=null){
				
				HandleMobileKeyboardInput();
				
			}
			#endif
			
		}