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); }
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); }
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); }
/// <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); }
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); }
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); }
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); }
/// <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(); } } }
/// <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 }