File modules/editor/codemirror/src/model/selection_updates.min.js
Last commit: Tue May 22 22:39:49 2018 +0200 Jan Dankert Fix für PHP 7.2: 'Object' darf nun nicht mehr als Klassennamen verwendet werden. AUCH NICHT IN EINEM NAMESPACE! WTF, wozu habe ich das in einen verfickten Namespace gepackt? Wozu soll der sonst da sein??? Amateure. Daher nun notgedrungen unbenannt in 'BaseObject'.
1 import { signalLater } from "../util/operation_group.js" 2 import { ensureCursorVisible } from "../display/scrolling.js" 3 import { clipPos, cmp, Pos } from "../line/pos.js" 4 import { getLine } from "../line/utils_line.js" 5 import { hasHandler, signal, signalCursorActivity } from "../util/event.js" 6 import { lst, sel_dontScroll } from "../util/misc.js" 7 8 import { addSelectionToHistory } from "./history.js" 9 import { normalizeSelection, Range, Selection, simpleSelection } from "./selection.js" 10 11 // The 'scroll' parameter given to many of these indicated whether 12 // the new cursor position should be scrolled into view after 13 // modifying the selection. 14 15 // If shift is held or the extend flag is set, extends a range to 16 // include a given position (and optionally a second position). 17 // Otherwise, simply returns the range between the given positions. 18 // Used for cursor motion and such. 19 export function extendRange(range, head, other, extend) { 20 if (extend) { 21 let anchor = range.anchor 22 if (other) { 23 let posBefore = cmp(head, anchor) < 0 24 if (posBefore != (cmp(other, anchor) < 0)) { 25 anchor = head 26 head = other 27 } else if (posBefore != (cmp(head, other) < 0)) { 28 head = other 29 } 30 } 31 return new Range(anchor, head) 32 } else { 33 return new Range(other || head, head) 34 } 35 } 36 37 // Extend the primary selection range, discard the rest. 38 export function extendSelection(doc, head, other, options, extend) { 39 if (extend == null) extend = doc.cm && (doc.cm.display.shift || doc.extend) 40 setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options) 41 } 42 43 // Extend all selections (pos is an array of selections with length 44 // equal the number of selections) 45 export function extendSelections(doc, heads, options) { 46 let out = [] 47 let extend = doc.cm && (doc.cm.display.shift || doc.extend) 48 for (let i = 0; i < doc.sel.ranges.length; i++) 49 out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend) 50 let newSel = normalizeSelection(out, doc.sel.primIndex) 51 setSelection(doc, newSel, options) 52 } 53 54 // Updates a single range in the selection. 55 export function replaceOneSelection(doc, i, range, options) { 56 let ranges = doc.sel.ranges.slice(0) 57 ranges[i] = range 58 setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options) 59 } 60 61 // Reset the selection to a single range. 62 export function setSimpleSelection(doc, anchor, head, options) { 63 setSelection(doc, simpleSelection(anchor, head), options) 64 } 65 66 // Give beforeSelectionChange handlers a change to influence a 67 // selection update. 68 function filterSelectionChange(doc, sel, options) { 69 let obj = { 70 ranges: sel.ranges, 71 update: function(ranges) { 72 this.ranges = [] 73 for (let i = 0; i < ranges.length; i++) 74 this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), 75 clipPos(doc, ranges[i].head)) 76 }, 77 origin: options && options.origin 78 } 79 signal(doc, "beforeSelectionChange", doc, obj) 80 if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj) 81 if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1) 82 else return sel 83 } 84 85 export function setSelectionReplaceHistory(doc, sel, options) { 86 let done = doc.history.done, last = lst(done) 87 if (last && last.ranges) { 88 done[done.length - 1] = sel 89 setSelectionNoUndo(doc, sel, options) 90 } else { 91 setSelection(doc, sel, options) 92 } 93 } 94 95 // Set a new selection. 96 export function setSelection(doc, sel, options) { 97 setSelectionNoUndo(doc, sel, options) 98 addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options) 99 } 100 101 export function setSelectionNoUndo(doc, sel, options) { 102 if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) 103 sel = filterSelectionChange(doc, sel, options) 104 105 let bias = options && options.bias || 106 (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1) 107 setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)) 108 109 if (!(options && options.scroll === false) && doc.cm) 110 ensureCursorVisible(doc.cm) 111 } 112 113 function setSelectionInner(doc, sel) { 114 if (sel.equals(doc.sel)) return 115 116 doc.sel = sel 117 118 if (doc.cm) { 119 doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true 120 signalCursorActivity(doc.cm) 121 } 122 signalLater(doc, "cursorActivity", doc) 123 } 124 125 // Verify that the selection does not partially select any atomic 126 // marked ranges. 127 export function reCheckSelection(doc) { 128 setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false)) 129 } 130 131 // Return a selection that does not partially select any atomic 132 // ranges. 133 function skipAtomicInSelection(doc, sel, bias, mayClear) { 134 let out 135 for (let i = 0; i < sel.ranges.length; i++) { 136 let range = sel.ranges[i] 137 let old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i] 138 let newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear) 139 let newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear) 140 if (out || newAnchor != range.anchor || newHead != range.head) { 141 if (!out) out = sel.ranges.slice(0, i) 142 out[i] = new Range(newAnchor, newHead) 143 } 144 } 145 return out ? normalizeSelection(out, sel.primIndex) : sel 146 } 147 148 function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { 149 let line = getLine(doc, pos.line) 150 if (line.markedSpans) for (let i = 0; i < line.markedSpans.length; ++i) { 151 let sp = line.markedSpans[i], m = sp.marker 152 if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && 153 (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) { 154 if (mayClear) { 155 signal(m, "beforeCursorEnter") 156 if (m.explicitlyCleared) { 157 if (!line.markedSpans) break 158 else {--i; continue} 159 } 160 } 161 if (!m.atomic) continue 162 163 if (oldPos) { 164 let near = m.find(dir < 0 ? 1 : -1), diff 165 if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft) 166 near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null) 167 if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) 168 return skipAtomicInner(doc, near, pos, dir, mayClear) 169 } 170 171 let far = m.find(dir < 0 ? -1 : 1) 172 if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight) 173 far = movePos(doc, far, dir, far.line == pos.line ? line : null) 174 return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null 175 } 176 } 177 return pos 178 } 179 180 // Ensure a given position is not inside an atomic range. 181 export function skipAtomic(doc, pos, oldPos, bias, mayClear) { 182 let dir = bias || 1 183 let found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || 184 (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || 185 skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || 186 (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)) 187 if (!found) { 188 doc.cantEdit = true 189 return Pos(doc.first, 0) 190 } 191 return found 192 } 193 194 function movePos(doc, pos, dir, line) { 195 if (dir < 0 && pos.ch == 0) { 196 if (pos.line > doc.first) return clipPos(doc, Pos(pos.line - 1)) 197 else return null 198 } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { 199 if (pos.line < doc.first + doc.size - 1) return Pos(pos.line + 1, 0) 200 else return null 201 } else { 202 return new Pos(pos.line, pos.ch + dir) 203 } 204 } 205 206 export function selectAll(cm) { 207 cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll) 208 }
Downloadmodules/editor/codemirror/src/model/selection_updates.min.js
History Tue, 22 May 2018 22:39:49 +0200 Jan Dankert Fix für PHP 7.2: 'Object' darf nun nicht mehr als Klassennamen verwendet werden. AUCH NICHT IN EINEM NAMESPACE! WTF, wozu habe ich das in einen verfickten Namespace gepackt? Wozu soll der sonst da sein??? Amateure. Daher nun notgedrungen unbenannt in 'BaseObject'.