static bool FindCommonGround(CssBoxHitChain startChain, CssBoxHitChain endChain, out int breakAtLevel) { //find common ground of startChain and endChain int startChainCount = startChain.Count; int endChainCount = endChain.Count; int lim = Math.Min(startChainCount, endChainCount); //from root to leave breakAtLevel = 0; for (int i = 0; i < lim; ++i) { HitInfo startHitInfo = startChain.GetHitInfo(i); HitInfo endHitInfo = endChain.GetHitInfo(i); if (startHitInfo.hitObject != endHitInfo.hitObject) { //found diff here breakAtLevel = i; break; } } //---------------------------- //check //return isDeepDown = endChainCount > startChainCount && (breakAtLevel == startChainCount - 1); return(endChainCount > startChainCount && (breakAtLevel == startChainCount - 1)); }
static bool IsOnTheSameLine(CssBoxHitChain startChain, CssBoxHitChain endChain) { CssLineBox startLineBox = GetLine(startChain.GetLastHit()); CssLineBox endLineBox = GetLine(endChain.GetLastHit()); return(startLineBox != null && startLineBox == endLineBox); }
void SetupStartHitPoint(CssBoxHitChain startChain, ITextService textService) { //find global location of start point HitInfo startHit = startChain.GetLastHit(); //----------------------------- _startHitRun = null; _startHitRunCharIndex = 0; switch (startHit.hitObjectKind) { case HitObjectKind.Run: { CssRun run = (CssRun)startHit.hitObject; //------------------------------------------------------- int sel_index; int sel_offset; run.FindSelectionPoint(textService, startHit.localX, out sel_index, out sel_offset); _startHitRunCharIndex = sel_index; //modify hitpoint _startHitHostLine = (CssLineBox)startChain.GetHitInfo(startChain.Count - 2).hitObject; _startLineBeginSelectionAtPixel = (int)(run.Left + sel_offset); _startHitRun = run; } break; case HitObjectKind.LineBox: { _startHitHostLine = (CssLineBox)startHit.hitObject; _startLineBeginSelectionAtPixel = startHit.localX; //make global } break; case HitObjectKind.CssBox: { CssBox box = (CssBox)startHit.hitObject; //find first nearest line at point CssLineBox startHitLine = FindNearestLine(box, startChain.RootGlobalY, 5); _startLineBeginSelectionAtPixel = 0; if (startHitLine != null) { _startHitHostLine = startHitLine; } else { //if not found? _startHitHostLine = null; } } break; default: { throw new NotSupportedException(); } } }
public void MouseDown(UIMouseEventArgs e, CssBox startAt) { if (!_isBinded) { return; } if (startAt == null) { return; } //---------------------------------------------------- ClearPreviousSelection(); if (_latestMouseDownChain != null) { ReleaseHitChain(_latestMouseDownChain); _latestMouseDownChain = null; } this.lastDomLayoutVersion = this._htmlContainer.LayoutVersion; //---------------------------------------------------- int x = e.X; int y = e.Y; this._mouseDownStartAt = startAt; this._mousedownX = x; this._mousedownY = y; CssBoxHitChain hitChain = GetFreeHitChain(); hitChain.SetRootGlobalPosition(x, y); //1. hittest BoxHitUtils.HitTest(startAt, x, y, hitChain); //2. propagate events SetEventOrigin(e, hitChain); ForEachOnlyEventPortalBubbleUp(e, hitChain, (portal) => { portal.PortalMouseDown(e); return(true); }); if (!e.CancelBubbling) { var prevMouseDownElement = this.currentMouseDown; e.CurrentContextElement = this.currentMouseDown = null; //clear ForEachEventListenerBubbleUp(e, hitChain, () => { //TODO: check accept keyboard this.currentMouseDown = e.CurrentContextElement; e.CurrentContextElement.ListenMouseDown(e); if (prevMouseDownElement != null && prevMouseDownElement != currentMouseDown) { prevMouseDownElement.ListenLostMouseFocus(e); } return(e.CancelBubbling); }); } //---------------------------------- //save mousedown hitchain this._latestMouseDownChain = hitChain; }
static void SetEventOrigin(UIEventArgs e, CssBoxHitChain hitChain) { int count = hitChain.Count; if (count > 0) { e.SetExactHitObject(hitChain.GetHitInfo(count - 1).hitObject); } }
static void SetEventOrigin(UIEventArgs e, CssBoxHitChain hitChain) { int count = hitChain.Count; if (count > 0) { var hitInfo = hitChain.GetHitInfo(count - 1); e.ExactHitObject = hitInfo.hitObject; } }
public void MouseDown(UIMouseEventArgs e, CssBox startAt) { if (!_isBinded) return; if (startAt == null) return; //---------------------------------------------------- ClearPreviousSelection(); if (_latestMouseDownChain != null) { ReleaseHitChain(_latestMouseDownChain); _latestMouseDownChain = null; } this.lastDomLayoutVersion = this._htmlContainer.LayoutVersion; //---------------------------------------------------- int x = e.X; int y = e.Y; this._mouseDownStartAt = startAt; this._mousedownX = x; this._mousedownY = y; CssBoxHitChain hitChain = GetFreeHitChain(); hitChain.SetRootGlobalPosition(x, y); //1. hittest BoxHitUtils.HitTest(startAt, x, y, hitChain); //2. propagate events SetEventOrigin(e, hitChain); ForEachOnlyEventPortalBubbleUp(e, hitChain, (portal) => { portal.PortalMouseDown(e); return true; }); if (!e.CancelBubbling) { var prevMouseDownElement = this.currentMouseDown; e.CurrentContextElement = this.currentMouseDown = null; //clear ForEachEventListenerBubbleUp(e, hitChain, () => { //TODO: check accept keyboard this.currentMouseDown = e.CurrentContextElement; e.CurrentContextElement.ListenMouseDown(e); if (prevMouseDownElement != null && prevMouseDownElement != currentMouseDown) { prevMouseDownElement.ListenLostMouseFocus(e); } return e.CancelBubbling; }); } //---------------------------------- //save mousedown hitchain this._latestMouseDownChain = hitChain; }
static void ForEachEventListenerBubbleUp(UIEventArgs e, CssBoxHitChain hitChain, EventListenerAction listenerAction) { for (int i = hitChain.Count - 1; i >= 0; --i) { //propagate up var hitInfo = hitChain.GetHitInfo(i); IEventListener controller = null; switch (hitInfo.hitObjectKind) { default: { continue; } case HitObjectKind.Run: { CssRun run = (CssRun)hitInfo.hitObject; controller = CssBox.UnsafeGetController(run.OwnerBox) as IEventListener; } break; case HitObjectKind.CssBox: { CssBox box = (CssBox)hitInfo.hitObject; controller = CssBox.UnsafeGetController(box) as IEventListener; } break; } //--------------------- if (controller != null) { //found controller if (e.SourceHitElement == null) { e.SourceHitElement = controller; } e.CurrentContextElement = controller; e.SetLocation(hitInfo.localX, hitInfo.localY); if (listenerAction()) { return; } } } }
static void ForEachOnlyEventPortalBubbleUp(UIEventArgs e, CssBoxHitChain hitPointChain, EventPortalAction eventPortalAction) { //only listener that need tunnel down for (int i = hitPointChain.Count - 1; i >= 0; --i) { //propagate up var hitInfo = hitPointChain.GetHitInfo(i); IEventPortal controller = null; switch (hitInfo.hitObjectKind) { default: { continue; } case HitObjectKind.Run: { CssRun run = (CssRun)hitInfo.hitObject; controller = CssBox.UnsafeGetController(run.OwnerBox) as IEventPortal; } break; case HitObjectKind.CssBox: { CssBox box = (CssBox)hitInfo.hitObject; controller = CssBox.UnsafeGetController(box) as IEventPortal; } break; } //--------------------- if (controller != null) { e.SetLocation(hitInfo.localX, hitInfo.localY); if (eventPortalAction(controller)) { return; } } } }
public SelectionRange( CssBoxHitChain startChain, CssBoxHitChain endChain, IFonts ifonts) { if (IsOnTheSameLine(startChain, endChain)) { //on the same line if (endChain.RootGlobalX < startChain.RootGlobalX) { //swap var tmp = endChain; endChain = startChain; startChain = tmp; } } else { //across line if (endChain.RootGlobalY < startChain.RootGlobalY) { //swap var tmp = endChain; endChain = startChain; startChain = tmp; } } //1. this.SetupStartHitPoint(startChain, ifonts); //2. if (this.startHitHostLine == null) { this.isValid = false; return; } this.SetupEndHitPoint(startChain, endChain, ifonts); this.snapSelectionArea = this.GetSelectionRectArea(); }
public SelectionRange( CssBoxHitChain startChain, CssBoxHitChain endChain, ITextService ifonts) { if (IsOnTheSameLine(startChain, endChain)) { //on the same line if (endChain.RootGlobalX < startChain.RootGlobalX) { //swap var tmp = endChain; endChain = startChain; startChain = tmp; } } else { //across line if (endChain.RootGlobalY < startChain.RootGlobalY) { //swap var tmp = endChain; endChain = startChain; startChain = tmp; } } //1. this.SetupStartHitPoint(startChain, ifonts); //2. if (this.startHitHostLine == null) { this.isValid = false; return; } this.SetupEndHitPoint(startChain, endChain, ifonts); this.snapSelectionArea = this.GetSelectionRectArea(); }
internal SelectionRange( CssBoxHitChain startChain, CssBoxHitChain endChain, IHtmlTextService textservice) { if (IsOnTheSameLine(startChain, endChain)) { //on the same line if (endChain.RootGlobalX < startChain.RootGlobalX) { //swap CssBoxHitChain tmp = endChain; endChain = startChain; startChain = tmp; } } else { //across line if (endChain.RootGlobalY < startChain.RootGlobalY) { //swap CssBoxHitChain tmp = endChain; endChain = startChain; startChain = tmp; } } //1. this.SetupStartHitPoint(startChain, textservice); //2. if (_startHitHostLine == null) { IsValid = false; return; } this.SetupEndHitPoint(startChain, endChain, textservice); SnapSelectionArea = this.GetSelectionRectArea(); }
public void MouseUp(UIMouseEventArgs e, CssBox startAt) { if (!_isBinded) { return; } if (startAt == null) { return; } //---------------------------------------------------- DateTime snapMouseUpTime = DateTime.Now; TimeSpan timediff = snapMouseUpTime - lastimeMouseUp; bool isAlsoDoubleClick = timediff.Milliseconds < DOUBLE_CLICK_SENSE; this.lastimeMouseUp = snapMouseUpTime; //----------------------------------------- CssBoxHitChain hitChain = GetFreeHitChain(); hitChain.SetRootGlobalPosition(e.X, e.Y); //1. prob hit chain only BoxHitUtils.HitTest(startAt, e.X, e.Y, hitChain); SetEventOrigin(e, hitChain); //2. invoke css event and script event ForEachOnlyEventPortalBubbleUp(e, hitChain, (portal) => { portal.PortalMouseUp(e); return(true); }); if (!e.CancelBubbling) { ForEachEventListenerBubbleUp(e, hitChain, () => { e.CurrentContextElement.ListenMouseUp(e); return(e.CancelBubbling); }); } if (!e.IsCanceled) { //-------------------- //click or double click //-------------------- if (isAlsoDoubleClick) { ForEachEventListenerBubbleUp(e, hitChain, () => { e.CurrentContextElement.ListenMouseDoubleClick(e); return(e.CancelBubbling); }); } else { ForEachEventListenerBubbleUp(e, hitChain, () => { e.CurrentContextElement.ListenMouseClick(e); return(e.CancelBubbling); }); } } ReleaseHitChain(hitChain); if (this._latestMouseDownChain != null) { this._latestMouseDownChain.Clear(); //Console.WriteLine(dbugNN++); this._latestMouseDownChain = null; } }
public void MouseDown(UIMouseDownEventArgs e, CssBox startAt) { if (!_isBinded) { return; } if (startAt == null) { return; } //---------------------------------------------------- if (!e.Shift) { ClearPreviousSelection(); } if (_latestMouseDownChain != null) { ReleaseHitChain(_latestMouseDownChain); _latestMouseDownChain = null; } _lastDomLayoutVersion = _htmlVisualRoot.LayoutVersion; //---------------------------------------------------- int x = e.X; int y = e.Y; _mouseDownStartAt = startAt; _mousedownX = x; _mousedownY = y; CssBoxHitChain hitChain = GetFreeHitChain(); #if DEBUG hitChain.debugEventPhase = CssBoxHitChain.dbugEventPhase.MouseDown; #endif hitChain.SetRootGlobalPosition(x, y); //1. hittest BoxHitUtils.HitTest(startAt, x, y, hitChain); //2. propagate events SetEventOrigin(e, hitChain); ForEachOnlyEventPortalBubbleUp(e, hitChain, portal => { portal.PortalMouseDown(e); return(true); }); if (!e.CancelBubbling) { IUIEventListener prevMouseDownElement = _currentMouseDown; _currentMouseDown = null; //clear e.SetCurrentContextElement(null); ForEachEventListenerBubbleUp(e, hitChain, () => { //TODO: check accept keyboard _currentMouseDown = e.CurrentContextElement; e.CurrentContextElement.ListenMouseDown(e); if (prevMouseDownElement != null && prevMouseDownElement != _currentMouseDown) { prevMouseDownElement.ListenLostMouseFocus(_mouseLostFocus); } return(e.CancelBubbling); }); } //---------------------------------- //save mousedown hitchain _latestMouseDownChain = hitChain; }
public void MouseMove(UIMouseEventArgs e, CssBox startAt) { if (!_isBinded) { return; } if (startAt == null) { return; } //----------------------------------------- int x = e.X; int y = e.Y; if (e.IsDragging && _latestMouseDownChain != null) { //dragging *** , if changed if (this._mousedownX != x || this._mousedownY != y) { //handle mouse drag CssBoxHitChain hitChain = GetFreeHitChain(); hitChain.SetRootGlobalPosition(x, y); BoxHitUtils.HitTest(startAt, x, y, hitChain); SetEventOrigin(e, hitChain); //--------------------------------------------------------- //propagate mouse drag ForEachOnlyEventPortalBubbleUp(e, hitChain, (portal) => { portal.PortalMouseMove(e); return(true); }); //--------------------------------------------------------- if (!e.CancelBubbling) { ClearPreviousSelection(); if (_latestMouseDownChain.Count > 0 && hitChain.Count > 0) { if (this._htmlContainer.LayoutVersion != this.lastDomLayoutVersion) { //the dom has been changed so... //need to evaluate hitchain at mousedown position again int lastRootGlobalX = _latestMouseDownChain.RootGlobalX; int lastRootGlobalY = _latestMouseDownChain.RootGlobalY; _latestMouseDownChain.Clear(); _latestMouseDownChain.SetRootGlobalPosition(lastRootGlobalX, lastRootGlobalY); BoxHitUtils.HitTest(_mouseDownStartAt, lastRootGlobalX, lastRootGlobalY, _latestMouseDownChain); } //create selection range var newSelectionRange = new SelectionRange( _latestMouseDownChain, hitChain, this.ifonts); if (newSelectionRange.IsValid) { this._htmlContainer.SetSelection(newSelectionRange); } else { this._htmlContainer.SetSelection(null); } } else { this._htmlContainer.SetSelection(null); } ForEachEventListenerBubbleUp(e, hitChain, () => { e.CurrentContextElement.ListenMouseMove(e); return(true); }); } //--------------------------------------------------------- ReleaseHitChain(hitChain); } } else { //mouse move //--------------------------------------------------------- CssBoxHitChain hitChain = GetFreeHitChain(); hitChain.SetRootGlobalPosition(x, y); BoxHitUtils.HitTest(startAt, x, y, hitChain); SetEventOrigin(e, hitChain); //--------------------------------------------------------- ForEachOnlyEventPortalBubbleUp(e, hitChain, (portal) => { portal.PortalMouseMove(e); return(true); }); //--------------------------------------------------------- if (!e.CancelBubbling) { ForEachEventListenerBubbleUp(e, hitChain, () => { e.CurrentContextElement.ListenMouseMove(e); return(true); }); } ReleaseHitChain(hitChain); } }
public virtual bool CustomContentHitTest(float x, float y, CssBoxHitChain hitChain) { throw new NotImplementedException(); }
public override bool CustomContentHitTest(float x, float y, CssBoxHitChain hitChain) { return true;//stop here }
void ReleaseHitChain(CssBoxHitChain hitChain) { hitChain.Clear(); this.hitChainPools.Push(hitChain); }
public void MouseUp(UIMouseEventArgs e, CssBox startAt) { if (!_isBinded) return; if (startAt == null) return; //---------------------------------------------------- DateTime snapMouseUpTime = DateTime.Now; TimeSpan timediff = snapMouseUpTime - lastimeMouseUp; bool isAlsoDoubleClick = timediff.Milliseconds < DOUBLE_CLICK_SENSE; this.lastimeMouseUp = snapMouseUpTime; //----------------------------------------- CssBoxHitChain hitChain = GetFreeHitChain(); hitChain.SetRootGlobalPosition(e.X, e.Y); //1. prob hit chain only BoxHitUtils.HitTest(startAt, e.X, e.Y, hitChain); SetEventOrigin(e, hitChain); //2. invoke css event and script event ForEachOnlyEventPortalBubbleUp(e, hitChain, (portal) => { portal.PortalMouseUp(e); return true; }); if (!e.CancelBubbling) { ForEachEventListenerBubbleUp(e, hitChain, () => { e.CurrentContextElement.ListenMouseUp(e); return e.CancelBubbling; }); } if (!e.IsCanceled) { //-------------------- //click or double click //-------------------- if (isAlsoDoubleClick) { ForEachEventListenerBubbleUp(e, hitChain, () => { e.CurrentContextElement.ListenMouseDoubleClick(e); return e.CancelBubbling; }); } else { ForEachEventListenerBubbleUp(e, hitChain, () => { e.CurrentContextElement.ListenMouseClick(e); return e.CancelBubbling; }); } } ReleaseHitChain(hitChain); if (this._latestMouseDownChain != null) { this._latestMouseDownChain.Clear(); //Console.WriteLine(dbugNN++); this._latestMouseDownChain = null; } }
static bool FindCommonGround(CssBoxHitChain startChain, CssBoxHitChain endChain, out int breakAtLevel) { //find common ground of startChain and endChain int startChainCount = startChain.Count; int endChainCount = endChain.Count; int lim = Math.Min(startChainCount, endChainCount); //from root to leave breakAtLevel = 0; for (int i = 0; i < lim; ++i) { var startHitInfo = startChain.GetHitInfo(i); var endHitInfo = endChain.GetHitInfo(i); if (startHitInfo.hitObject != endHitInfo.hitObject) { //found diff here breakAtLevel = i; break; } } //---------------------------- //check //return isDeepDown = endChainCount > startChainCount && (breakAtLevel == startChainCount - 1); return endChainCount > startChainCount && (breakAtLevel == startChainCount - 1); }
void SetupEndHitPoint(CssBoxHitChain startChain, CssBoxHitChain endChain, ITextService textService) { //find global location of end point HitInfo endHit = endChain.GetLastHit(); int xposOnEndLine = 0; CssLineBox endline = null; //find endline first _endHitRunCharIndex = 0; _endHitRun = null; switch (endHit.hitObjectKind) { default: { throw new NotSupportedException(); } case HitObjectKind.Run: { CssRun endRun = (CssRun)endHit.hitObject; #if DEBUG //if (endRun.Text != null && endRun.Text.Contains("Jose")) //{ //} if (endHit.localX > 23) { } System.Diagnostics.Debug.WriteLine(endHit.localX); #endif endRun.FindSelectionPoint(textService, endHit.localX, out int run_sel_index, out int run_sel_offset); endline = endRun.HostLine; xposOnEndLine = (int)(endRun.Left + run_sel_offset); _endHitRunCharIndex = run_sel_index; #if DEBUG System.Diagnostics.Debug.WriteLine(_endHitRunCharIndex); #endif _endHitRun = endRun; } break; case HitObjectKind.LineBox: { endline = (CssLineBox)endHit.hitObject; xposOnEndLine = endHit.localX; } break; case HitObjectKind.CssBox: { CssBox hitBox = (CssBox)endHit.hitObject; endline = FindNearestLine(hitBox, endChain.RootGlobalY, 5); xposOnEndLine = endHit.localX; } break; } #if DEBUG if (xposOnEndLine == 0) { } #endif //---------------------------------- _selectedLines = new List <CssLineBox>(); if (_startHitHostLine == endline) { _selectedLines.Add(endline); _startHitHostLine.Select(_startLineBeginSelectionAtPixel, xposOnEndLine, _startHitRun, _startHitRunCharIndex, _endHitRun, _endHitRunCharIndex); return; //early exit here *** } //---------------------------------- //select on different line LineWalkVisitor lineWalkVisitor = null; if (FindCommonGround(startChain, endChain, out int breakAtLevel) && breakAtLevel > 0) { CssBlockRun hitBlockRun = endChain.GetHitInfo(breakAtLevel).hitObject as CssBlockRun; //multiple select //1. first part if (hitBlockRun != null) { _startHitHostLine.Select(_startLineBeginSelectionAtPixel, (int)hitBlockRun.Left, _startHitRun, _startHitRunCharIndex, _endHitRun, _endHitRunCharIndex); _selectedLines.Add(_startHitHostLine); lineWalkVisitor = new LineWalkVisitor(hitBlockRun); } else { _startHitHostLine.SelectPartialToEnd(_startLineBeginSelectionAtPixel, _startHitRun, _startHitRunCharIndex); _selectedLines.Add(_startHitHostLine); lineWalkVisitor = new LineWalkVisitor(_startHitHostLine); } } else { _startHitHostLine.SelectPartialToEnd(_startLineBeginSelectionAtPixel, _startHitRun, _startHitRunCharIndex); _selectedLines.Add(_startHitHostLine); lineWalkVisitor = new LineWalkVisitor(_startHitHostLine); } lineWalkVisitor.SetWalkTargetPosition(endChain.RootGlobalX, endChain.RootGlobalY); #if DEBUG int dbugExpectedId = 1; #endif lineWalkVisitor.Walk(endline, (lineCoverage, linebox, partialLineRun) => { #if DEBUG //System.Diagnostics.Debug.WriteLine("sel:" + linebox.dbugId); if (dbugExpectedId != linebox.dbugId) { } dbugExpectedId++; #endif switch (lineCoverage) { case LineCoverage.EndLine: { //found end line linebox.SelectPartialFromStart(xposOnEndLine, _endHitRun, _endHitRunCharIndex); _selectedLines.Add(linebox); } break; case LineCoverage.PartialLine: { linebox.SelectPartialFromStart((int)partialLineRun.Right, _endHitRun, _endHitRunCharIndex); _selectedLines.Add(linebox); } break; case LineCoverage.FullLine: { //check if hitpoint is in the line area linebox.SelectFull(); _selectedLines.Add(linebox); } break; } }); }
void SetupEndHitPoint(CssBoxHitChain startChain, CssBoxHitChain endChain, ITextService ifonts) { //find global location of end point HitInfo endHit = endChain.GetLastHit(); int xposOnEndLine = 0; CssLineBox endline = null; int run_sel_offset = 0; //find endline first this.endHitRunCharIndex = 0; this.endHitRun = null; switch (endHit.hitObjectKind) { default: { throw new NotSupportedException(); } case HitObjectKind.Run: { CssRun endRun = (CssRun)endHit.hitObject; //if (endRun.Text != null && endRun.Text.Contains("Jose")) //{ //} int run_sel_index; endRun.FindSelectionPoint(ifonts, endHit.localX, out run_sel_index, out run_sel_offset); endline = endRun.HostLine; xposOnEndLine = (int)(endRun.Left + run_sel_offset); this.endHitRunCharIndex = run_sel_index; this.endHitRun = endRun; } break; case HitObjectKind.LineBox: { endline = (CssLineBox)endHit.hitObject; xposOnEndLine = endHit.localX; } break; case HitObjectKind.CssBox: { CssBox hitBox = (CssBox)endHit.hitObject; endline = FindNearestLine(hitBox, endChain.RootGlobalY, 5); xposOnEndLine = endHit.localX; } break; } #if DEBUG if (xposOnEndLine == 0) { } #endif //---------------------------------- this.selectedLines = new List <CssLineBox>(); if (startHitHostLine == endline) { this.selectedLines.Add(endline); startHitHostLine.Select(startLineBeginSelectionAtPixel, xposOnEndLine, this.startHitRun, this.startHitRunCharIndex, this.endHitRun, this.endHitRunCharIndex); return; //early exit here *** } //---------------------------------- //select on different line LineWalkVisitor lineWalkVisitor = null; int breakAtLevel; if (FindCommonGround(startChain, endChain, out breakAtLevel) && breakAtLevel > 0) { var hit1 = endChain.GetHitInfo(breakAtLevel).hitObject; var hitBlockRun = hit1 as CssBlockRun; //multiple select //1. first part if (hitBlockRun != null) { startHitHostLine.Select(startLineBeginSelectionAtPixel, (int)hitBlockRun.Left, this.startHitRun, this.startHitRunCharIndex, this.endHitRun, this.endHitRunCharIndex); selectedLines.Add(this.startHitHostLine); lineWalkVisitor = new LineWalkVisitor(hitBlockRun); } else { startHitHostLine.SelectPartialToEnd(startLineBeginSelectionAtPixel, this.startHitRun, this.startHitRunCharIndex); selectedLines.Add(this.startHitHostLine); lineWalkVisitor = new LineWalkVisitor(startHitHostLine); } } else { startHitHostLine.SelectPartialToEnd(startLineBeginSelectionAtPixel, this.startHitRun, this.startHitRunCharIndex); selectedLines.Add(this.startHitHostLine); lineWalkVisitor = new LineWalkVisitor(startHitHostLine); } lineWalkVisitor.SetWalkTargetPosition(endChain.RootGlobalX, endChain.RootGlobalY); lineWalkVisitor.Walk(endline, (lineCoverage, linebox, partialLineRun) => { switch (lineCoverage) { case LineCoverage.EndLine: { //found end line linebox.SelectPartialFromStart(xposOnEndLine, this.endHitRun, this.endHitRunCharIndex); selectedLines.Add(linebox); } break; case LineCoverage.PartialLine: { linebox.SelectPartialFromStart((int)partialLineRun.Right, this.endHitRun, this.endHitRunCharIndex); selectedLines.Add(linebox); } break; case LineCoverage.FullLine: { //check if hitpoint is in the line area linebox.SelectFull(); selectedLines.Add(linebox); } break; } }); }
public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain) { //-------------------------------------- float boxHitLocalX = x - box.LocalX; float boxHitLocalY = y - box.LocalY; bool isPointInArea = box.IsPointInArea(x, y); //---------------------------------------------------------------------- if (isPointInArea) { hitChain.AddHit(box, (int)boxHitLocalX, (int)boxHitLocalY); } //check absolute layer first *** if (box.HasAbsoluteLayer) { hitChain.PushContextBox(box); foreach (var absBox in box.GetAbsoluteChildBoxBackwardIter()) { if (HitTest(absBox, boxHitLocalX, boxHitLocalY, hitChain)) { //found hit hitChain.PopContextBox(box); return(true); } } hitChain.PopContextBox(box); } //---------------------------------------------------------------------- if (!isPointInArea) { switch (box.CssDisplay) { case Css.CssDisplay.TableRow: { foreach (var childBox in box.GetChildBoxIter()) { if (HitTest(childBox, x, y, hitChain)) { return(true); } } } break; } //exit return(false); } //---------------------------------------------------------------------- //at here point is in the area*** hitChain.PushContextBox(box); if (box.IsCustomCssBox) { //custom css box //return true= stop here if (box.CustomContentHitTest(x, y, hitChain)) { hitChain.PopContextBox(box); return(true); } } if (box.LineBoxCount > 0) { bool foundSomeLine = false; foreach (var lineBox in box.GetLineBoxIter()) { //line box not overlap if (lineBox.HitTest(boxHitLocalX, boxHitLocalY)) { foundSomeLine = true; float lineBoxLocalY = boxHitLocalY - lineBox.CachedLineTop; //2. hitChain.AddHit(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY); var foundRun = BoxHitUtils.GetCssRunOnLocation(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY); if (foundRun != null) { //3. hitChain.AddHit(foundRun, (int)(boxHitLocalX - foundRun.Left), (int)lineBoxLocalY); //4. go deeper for block run if (foundRun.Kind == CssRunKind.BlockRun) { var blockRun = (CssBlockRun)foundRun; CssLineBox hostLine = blockRun.HostLine; //adjust with hostline HitTest(((CssBlockRun)foundRun).ContentBox, (int)(boxHitLocalX - foundRun.Left), boxHitLocalY - hostLine.CachedLineTop, hitChain); } } //found line box hitChain.PopContextBox(box); return(true); } else if (foundSomeLine) { return(false); } } } else { //iterate in child foreach (var childBox in box.GetChildBoxIter()) { if (HitTest(childBox, boxHitLocalX, boxHitLocalY, hitChain)) { //recursive hitChain.PopContextBox(box); return(true); } } } hitChain.PopContextBox(box); return(true); }
public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain) { #if DEBUG //if (box.ViewportY != 0 && hitChain.debugEventPhase == CssBoxHitChain.dbugEventPhase.MouseDown) //{ //} #endif //-------------------------------------- bool isPointInArea = box.IsPointInArea(x, y); float boxHitLocalX = x - box.LocalX; //** float boxHitLocalY = y - box.LocalY; //** //---------------------------------------------------------------------- if (isPointInArea) { hitChain.AddHit(box, (int)boxHitLocalX, (int)boxHitLocalY); } //---------------------------------------------------------------------- //enter children space -> offset with its viewport boxHitLocalX += box.ViewportX; boxHitLocalY += box.ViewportY; //check absolute layer first *** if (box.HasAbsoluteLayer) { hitChain.PushContextBox(box); foreach (CssBox absBox in box.GetAbsoluteChildBoxBackwardIter()) { if (HitTest(absBox, boxHitLocalX, boxHitLocalY, hitChain)) { //found hit hitChain.PopContextBox(box); return(true); } } hitChain.PopContextBox(box); } //---------------------------------------------------------------------- if (!isPointInArea) { switch (box.CssDisplay) { case Css.CssDisplay.TableRow: { foreach (CssBox childBox in box.GetChildBoxIter()) { if (HitTest(childBox, boxHitLocalX, boxHitLocalY, hitChain)) { return(true); } } } break; } //exit return(false); } //---------------------------------------------------------------------- //at here point is in the area*** hitChain.PushContextBox(box); if (box.IsCustomCssBox) { //custom css box //return true= stop here if (box.CustomContentHitTest(boxHitLocalX, boxHitLocalY, hitChain)) { hitChain.PopContextBox(box); return(true); } } if (box.LineBoxCount > 0) { bool foundSomeLine = false; foreach (CssLineBox lineBox in box.GetLineBoxIter()) { //line box not overlap if (lineBox.HitTest(boxHitLocalX, boxHitLocalY)) { foundSomeLine = true; float lineBoxLocalY = boxHitLocalY - lineBox.CachedLineTop; //2. hitChain.AddHit(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY); CssRun foundRun = BoxHitUtils.GetCssRunOnLocation(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY); //CssRun foundRun = BoxHitUtils.GetCssRunOnLocation(lineBox, (int)x, (int)y); if (foundRun != null) { //3. hitChain.AddHit(foundRun, (int)(boxHitLocalX - foundRun.Left), (int)lineBoxLocalY); //4. go deeper for block run if (foundRun.Kind == CssRunKind.BlockRun) { CssBlockRun blockRun = (CssBlockRun)foundRun; CssLineBox hostLine = blockRun.HostLine; //adjust with hostline HitTest(blockRun.ContentBox, (int)(boxHitLocalX + blockRun.ContentBox.LocalX - foundRun.Left), (int)(boxHitLocalY - hostLine.CachedLineTop), hitChain); } } //found line box hitChain.PopContextBox(box); return(true); } else if (foundSomeLine) { return(false); } } } else { //iterate in child //foreach (var childBox in box.GetChildBoxIter()) foreach (CssBox childBox in box.GetChildBoxBackwardIter()) { if (HitTest(childBox, boxHitLocalX, boxHitLocalY, hitChain)) { //recursive hitChain.PopContextBox(box); return(true); } } } hitChain.PopContextBox(box); return(true); }
public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain) { //-------------------------------------- float boxHitLocalX = x - box.LocalX; float boxHitLocalY = y - box.LocalY; bool isPointInArea = box.IsPointInArea(x, y); //---------------------------------------------------------------------- if (isPointInArea) { hitChain.AddHit(box, (int)boxHitLocalX, (int)boxHitLocalY); } //check absolute layer first *** if (box.HasAbsoluteLayer) { hitChain.PushContextBox(box); foreach (var absBox in box.GetAbsoluteChildBoxBackwardIter()) { if (HitTest(absBox, boxHitLocalX, boxHitLocalY, hitChain)) { //found hit hitChain.PopContextBox(box); return true; } } hitChain.PopContextBox(box); } //---------------------------------------------------------------------- if (!isPointInArea) { switch (box.CssDisplay) { case Css.CssDisplay.TableRow: { foreach (var childBox in box.GetChildBoxIter()) { if (HitTest(childBox, x, y, hitChain)) { return true; } } } break; } //exit return false; } //---------------------------------------------------------------------- //at here point is in the area*** hitChain.PushContextBox(box); if (box.IsCustomCssBox) { //custom css box //return true= stop here if (box.CustomContentHitTest(x, y, hitChain)) { hitChain.PopContextBox(box); return true; } } if (box.LineBoxCount > 0) { bool foundSomeLine = false; foreach (var lineBox in box.GetLineBoxIter()) { //line box not overlap if (lineBox.HitTest(boxHitLocalX, boxHitLocalY)) { foundSomeLine = true; float lineBoxLocalY = boxHitLocalY - lineBox.CachedLineTop; //2. hitChain.AddHit(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY); var foundRun = BoxHitUtils.GetCssRunOnLocation(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY); if (foundRun != null) { //3. hitChain.AddHit(foundRun, (int)(boxHitLocalX - foundRun.Left), (int)lineBoxLocalY); //4. go deeper for block run if (foundRun.Kind == CssRunKind.BlockRun) { var blockRun = (CssBlockRun)foundRun; CssLineBox hostLine = blockRun.HostLine; //adjust with hostline HitTest(((CssBlockRun)foundRun).ContentBox, (int)(boxHitLocalX - foundRun.Left), boxHitLocalY - hostLine.CachedLineTop, hitChain); } } //found line box hitChain.PopContextBox(box); return true; } else if (foundSomeLine) { return false; } } } else { //iterate in child foreach (var childBox in box.GetChildBoxIter()) { if (HitTest(childBox, boxHitLocalX, boxHitLocalY, hitChain)) { //recursive hitChain.PopContextBox(box); return true; } } } hitChain.PopContextBox(box); return true; }
void SetupEndHitPoint(CssBoxHitChain startChain, CssBoxHitChain endChain, IFonts ifonts) { //find global location of end point HitInfo endHit = endChain.GetLastHit(); int xposOnEndLine = 0; CssLineBox endline = null; int run_sel_offset = 0; //find endline first this.endHitRunCharIndex = 0; this.endHitRun = null; switch (endHit.hitObjectKind) { default: { throw new NotSupportedException(); } case HitObjectKind.Run: { CssRun endRun = (CssRun)endHit.hitObject; //if (endRun.Text != null && endRun.Text.Contains("Jose")) //{ //} int run_sel_index; endRun.FindSelectionPoint(ifonts, endHit.localX, out run_sel_index, out run_sel_offset); endline = endRun.HostLine; xposOnEndLine = (int)(endRun.Left + run_sel_offset); this.endHitRunCharIndex = run_sel_index; this.endHitRun = endRun; } break; case HitObjectKind.LineBox: { endline = (CssLineBox)endHit.hitObject; xposOnEndLine = endHit.localX; } break; case HitObjectKind.CssBox: { CssBox hitBox = (CssBox)endHit.hitObject; endline = FindNearestLine(hitBox, endChain.RootGlobalY, 5); xposOnEndLine = endHit.localX; } break; } #if DEBUG if (xposOnEndLine == 0) { } #endif //---------------------------------- this.selectedLines = new List<CssLineBox>(); if (startHitHostLine == endline) { this.selectedLines.Add(endline); startHitHostLine.Select(startLineBeginSelectionAtPixel, xposOnEndLine, this.startHitRun, this.startHitRunCharIndex, this.endHitRun, this.endHitRunCharIndex); return; //early exit here *** } //---------------------------------- //select on different line LineWalkVisitor lineWalkVisitor = null; int breakAtLevel; if (FindCommonGround(startChain, endChain, out breakAtLevel) && breakAtLevel > 0) { var hit1 = endChain.GetHitInfo(breakAtLevel).hitObject; var hitBlockRun = hit1 as CssBlockRun; //multiple select //1. first part if (hitBlockRun != null) { startHitHostLine.Select(startLineBeginSelectionAtPixel, (int)hitBlockRun.Left, this.startHitRun, this.startHitRunCharIndex, this.endHitRun, this.endHitRunCharIndex); selectedLines.Add(this.startHitHostLine); lineWalkVisitor = new LineWalkVisitor(hitBlockRun); } else { startHitHostLine.SelectPartialToEnd(startLineBeginSelectionAtPixel, this.startHitRun, this.startHitRunCharIndex); selectedLines.Add(this.startHitHostLine); lineWalkVisitor = new LineWalkVisitor(startHitHostLine); } } else { startHitHostLine.SelectPartialToEnd(startLineBeginSelectionAtPixel, this.startHitRun, this.startHitRunCharIndex); selectedLines.Add(this.startHitHostLine); lineWalkVisitor = new LineWalkVisitor(startHitHostLine); } lineWalkVisitor.SetWalkTargetPosition(endChain.RootGlobalX, endChain.RootGlobalY); lineWalkVisitor.Walk(endline, (lineCoverage, linebox, partialLineRun) => { switch (lineCoverage) { case LineCoverage.EndLine: { //found end line linebox.SelectPartialFromStart(xposOnEndLine, this.endHitRun, this.endHitRunCharIndex); selectedLines.Add(linebox); } break; case LineCoverage.PartialLine: { linebox.SelectPartialFromStart((int)partialLineRun.Right, this.endHitRun, this.endHitRunCharIndex); selectedLines.Add(linebox); } break; case LineCoverage.FullLine: { //check if hitpoint is in the line area linebox.SelectFull(); selectedLines.Add(linebox); } break; } }); }
void SetupStartHitPoint(CssBoxHitChain startChain, IFonts ifonts) { //find global location of start point HitInfo startHit = startChain.GetLastHit(); //----------------------------- this.startHitRun = null; this.startHitRunCharIndex = 0; switch (startHit.hitObjectKind) { case HitObjectKind.Run: { CssRun run = (CssRun)startHit.hitObject; //------------------------------------------------------- int sel_index; int sel_offset; run.FindSelectionPoint(ifonts, startHit.localX, out sel_index, out sel_offset); this.startHitRunCharIndex = sel_index; //modify hitpoint this.startHitHostLine = (CssLineBox)startChain.GetHitInfo(startChain.Count - 2).hitObject; this.startLineBeginSelectionAtPixel = (int)(run.Left + sel_offset); this.startHitRun = run; } break; case HitObjectKind.LineBox: { this.startHitHostLine = (CssLineBox)startHit.hitObject; this.startLineBeginSelectionAtPixel = startHit.localX; //make global } break; case HitObjectKind.CssBox: { CssBox box = (CssBox)startHit.hitObject; //find first nearest line at point CssLineBox startHitLine = FindNearestLine(box, startChain.RootGlobalY, 5); this.startLineBeginSelectionAtPixel = 0; if (startHitLine != null) { this.startHitHostLine = startHitLine; } else { //if not found? this.startHitHostLine = null; } } break; default: { throw new NotSupportedException(); } } }
public void MouseMove(UIMouseMoveEventArgs e, CssBox startAt) { if (!_isBinded) { return; } if (startAt == null) { return; } //----------------------------------------- int x = e.X; int y = e.Y; if (e.IsDragging && _latestMouseDownChain != null) { //dragging *** , if changed if (_mousedownX != x || _mousedownY != y) { //handle mouse drag CssBoxHitChain hitChain = GetFreeHitChain(); #if DEBUG hitChain.debugEventPhase = CssBoxHitChain.dbugEventPhase.MouseMove; #endif hitChain.SetRootGlobalPosition(x, y); BoxHitUtils.HitTest(startAt, x, y, hitChain); SetEventOrigin(e, hitChain); //--------------------------------------------------------- //propagate mouse drag ForEachOnlyEventPortalBubbleUp(e, hitChain, (portal) => { portal.PortalMouseMove(e); return(true); }); //--------------------------------------------------------- if (!e.CancelBubbling) { ClearPreviousSelection(); if (_latestMouseDownChain.Count > 0 && hitChain.Count > 0) { if (_htmlVisualRoot.LayoutVersion != _lastDomLayoutVersion) { //the dom has been changed so... //need to evaluate hitchain at mousedown position again int lastRootGlobalX = _latestMouseDownChain.RootGlobalX; int lastRootGlobalY = _latestMouseDownChain.RootGlobalY; _latestMouseDownChain.Clear(); _latestMouseDownChain.SetRootGlobalPosition(lastRootGlobalX, lastRootGlobalY); BoxHitUtils.HitTest(_mouseDownStartAt, lastRootGlobalX, lastRootGlobalY, _latestMouseDownChain); } //create selection range var newSelectionRange = new SelectionRange( _latestMouseDownChain, hitChain, _textService); if (newSelectionRange.IsValid) { _htmlVisualRoot.SetSelection(newSelectionRange); } else { _htmlVisualRoot.SetSelection(null); } } else { _htmlVisualRoot.SetSelection(null); } ForEachEventListenerBubbleUp(e, hitChain, () => { e.CurrentContextElement.ListenMouseMove(e); return(true); }); } //--------------------------------------------------------- ReleaseHitChain(hitChain); } } else { //mouse move //--------------------------------------------------------- CssBoxHitChain hitChain = GetFreeHitChain(); #if DEBUG hitChain.debugEventPhase = CssBoxHitChain.dbugEventPhase.MouseMove; #endif hitChain.SetRootGlobalPosition(x, y); BoxHitUtils.HitTest(startAt, x, y, hitChain); SetEventOrigin(e, hitChain); //--------------------------------------------------------- ForEachOnlyEventPortalBubbleUp(e, hitChain, (portal) => { portal.PortalMouseMove(e); return(true); }); //--------------------------------------------------------- if (!e.CancelBubbling) { ForEachEventListenerBubbleUp(e, hitChain, () => { e.CurrentContextElement.ListenMouseMove(e); return(true); }); } var cssbox = e.ExactHitObject as HtmlBoxes.CssBox; if (cssbox != null) { switch (cssbox.CursorName) { case Css.CssCursorName.IBeam: if (e.MouseCursorStyle != MouseCursorStyle.IBeam) { e.MouseCursorStyle = MouseCursorStyle.IBeam; } break; case Css.CssCursorName.Hand: case Css.CssCursorName.Pointer: if (e.MouseCursorStyle != MouseCursorStyle.Pointer) { e.MouseCursorStyle = MouseCursorStyle.Pointer; } break; case Css.CssCursorName.Default: if (e.MouseCursorStyle != MouseCursorStyle.Default) { e.MouseCursorStyle = MouseCursorStyle.Default; } break; } } else { var cssspan = e.ExactHitObject as HtmlBoxes.CssTextRun; if (cssspan != null) { cssbox = cssspan.OwnerBox; switch (cssbox.CursorName) { default: e.MouseCursorStyle = MouseCursorStyle.IBeam; break; case Css.CssCursorName.Hand: case Css.CssCursorName.Pointer: if (e.MouseCursorStyle != MouseCursorStyle.Pointer) { e.MouseCursorStyle = MouseCursorStyle.Pointer; } break; } } } ReleaseHitChain(hitChain); } }
public override bool CustomContentHitTest(float x, float y, CssBoxHitChain hitChain) { return(true);//stop here }
static bool IsOnTheSameLine(CssBoxHitChain startChain, CssBoxHitChain endChain) { CssLineBox startLineBox = GetLine(startChain.GetLastHit()); CssLineBox endLineBox = GetLine(endChain.GetLastHit()); return startLineBox != null && startLineBox == endLineBox; }