Preserve cursor position after setValue in Ace editor - ace-editor

I'm developing a real time editor with ace and call editor.setValue() when ever there is a change in the editor and the cursor positions itself at random positions below the text. What I want is pretty obvious, the cursor to position exactly where the text ends after the set value loads the new texts. Any ideas??

that is not very simple at all, because if the text have changed the same position will not be the same anymore.
if you want to restore the same selection, you can use toJSON method
before = editor.selection.toJSON();
editor.setValue(editor.getValue() + "xxx")
editor.selection.fromJSON(before)
but that in addition to being wasteful for performance, will not work correctly in the case when lines are shifted e.g. editor.setValue("xxx\n" + editor.getValue())
In general it is a better to use session.insert/session.remove methods
editor.session.insert({row: 0, column: 0}, "xxx\n")
editor.session.remove({start: {row: 0, column: 1}, end: {row: 1, column: 1}})

Related

Find cursor's coordinates in NSTextView

I have wrapping NSTextView instances stacked vertically, for example:
The quick brown fox
jumps over the lazy dog
Jackdaws love my big
sphinx of quartz
I need to move between them with up/down arrows. For example, when the cursor is positioned after the l in "lazy" and the user presses the down arrow, the cursor should jump right after the y in "my" – like it would do if these sentences were in the same text view.
By default, when the down arrow is pressed while the cursor is at the last wrapped line, a text view moves it to the end of that line. While I can use textView(_:doCommandBy:) in NSTextViewDelegate to detect the "arrow down" selector and override the default behavior, there are two problems:
I can determine if the cursor is at the last line by getting its position via the selectedRanges property and then checking for the newline character after this position, but it is not possible to know if it is at the last wrapped line, i.e. near the border of the current text view.
I need to know the X coordinate of the cursor to place it at approximately the same X coordinate in another text view (the fonts won't necessarily be fixed-width, so I can't rely on the character count).
I suppose both of them can be resolved via NSLayoutManager, but I can't wrap my head around all of its available methods.
It turned out to be relatively easy, here's what I've done (the examples are in C#). First, boundingRect(forGlyphRange:in:) gets the cursor's location in the current view:
var cursorLocation = new NSRange(CurrentTextView.SelectedRange.Location, 0);
var cursorCoordinates = CurrentTextView.LayoutManager.BoundingRectForGlyphRange(cursorLocation, CurrentTextView.TextContainer).Location;
Then if the second text view is below, the insertion point will be at 0 on the Y axis:
var insertionPoint = new CGPoint(cursorCoordinates.X, 0);
And if it is above, then another view's height should be used (reduced by 1, otherwise the resulting character index will be incorrect and the cursor will be placed at the end of the line):
var insertionPoint = new CGPoint(cursorCoordinates.X, AnotherTextView.Bounds.Size.Height - 1);
After getting the insertion point, another view needs to become the first responder and then characterIndexForInsertion(at:) does the job:
Window.MakeFirstResponder(AnotherTextView);
var index = AnotherTextView.CharacterIndex(insertionPoint);
AnotherTextView.SelectedRange = new NSRange(index, 0);

Assigning multiple keys for OrbitContorls in Three.js

I want to assign multiple keys for an event. (E.g. pressing [a] or [<-] do the same event.) I already had checked the OrbitControls Docs and
Keyboard Event Code.
I know 65 is 'A' and 37 is '<-', so I was expecting something like below. However, I couldn't find the right way (other than adding another eventHander) to assign both keys to a single event.
controls.key = {LEFT: [36, 65], UP: ... }
or
controls.key = {LEFT: 36 || 65, UP: ... }
Reference Doc (OrbitControls of Three.js)
What you want to do is not supported by OrbitControls. You can only assign a single value to LEFT, UP, RIGHT, BOTTOM. If you want a different behavior, you have to modify the class.
However, doing so should not be complicated since the only function you have to modify is handleKeyDown(). That's the place where event.keyCode is evaluated.
three.js R107

function-like interpolation in React Native?

I have a scrollview with fixed length in my RN project that should act like a parralax scroll behavior. When I scroll and move the Y component, the X component of the header is moving right so when it is on top, it is 56 pixels away from the left edge, leaving enough place for the back arrow.
But it is linear. Is there a way to make it exponential. The best example would be the WhatsApp contact's parralax scroll:
Watch the Title "Dune"
How I have it now = red line (linear)
How I would like to = blue line (linear with easing, exponential, whatever it's called)
I got the scaling animation done, but the linear motion is like a thorn in my eye and the documentation for Animated values is overwhelming and unclear a bit.
I've defined:
scrollY: new Animated.Value(0)
in state and in my scrollview like this:
<ScrollView
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.scrollY}}}]
)}
and my Animated.View inside of it looks like this:
<Animated.View
style={[
{marginTop: 30, alignSelf: 'flex-start' },
{translateX: headerTranslateX}
]}]}>
<Text>Title</Text>
</Animated.View>
Aand the interpolation:
const titleTranslateX = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE*0.6, HEADER_SCROLL_DISTANCE],
outputRange: [0, 0, 56],
extrapolate: 'clamp',
})
which is linear in nature (i tried setting 10+keypoints in inputRange and outputRange bit but it gets messy and doesn't look natural enough)
Any advice on how to achieve the desired effect?
The only thing it says in the Animated docs on easing (function interpolation) is:
Interpolation
Each property can be run through an interpolation first. An interpolation maps input ranges to output ranges, typically using a linear interpolation but also supports easing functions. By default, it will extrapolate the curve beyond the ranges given, but you can also have it clamp the output value.
It doesn't mention how you can add an easing function. However, in the source code you'll find this: https://github.com/facebook/react-native/blob/e2ce98b7c6f4f2fc7011c214f9edc1301ff30572/Libraries/Animated/src/Interpolation.js#L27
export type InterpolationConfigType = {
inputRange: Array<number>,
/* $FlowFixMe(>=0.38.0 site=react_native_fb,react_native_oss) - Flow error
* detected during the deployment of v0.38.0. To see the error, remove this
* comment and run flow
*/
outputRange: (Array<number> | Array<string>),
easing?: ((input: number) => number),
extrapolate?: ExtrapolateType,
extrapolateLeft?: ExtrapolateType,
extrapolateRight?: ExtrapolateType,
};
The easing function defaults to linear (t) => t, but you can make it any standard easing function. Here's a nice list: https://gist.github.com/gre/1650294
Note: this won't work if you're using useNativeDriver: true.
Hope this helps reduce the choppiness!

Why doesn't Synth.new understand about scales?

I can set a scale like this:
~pp = Scale.phrygian(\pythagorean);
I can then create a Pbind which plays the scale like this:
(
Pbind(
*[
instrument: \default,
scale: ~pp,
degree: Pseq([0, 1, 2, 3, 4, 5, 6, 7], inf),
amp: 0.5,
dur: 0.5
]
).play;
)
But Synth.new doesn't seem to get it at all (just results in silence):
b = Synth.new(\default, [\scale: ~pp, \degree: 3, \amp, 0.5]);
Interestingly, if I remove the scale parameter:
b = Synth.new(\default, [\degree: 3, \amp, 0.5]);
then I get a note, but it's always the same note. It doesn't respond to the degree parameter.
Ultimately, I would like to be able to trigger notes from an external OSC device (my phone!). This means hooking up OSCFunc to listen out for certain triggers, and play notes from a scale when those OSC events occur. I thought I could use Synth.new inside OSCFunc to actually play the notes, but it doesn't seem to know about scales, so I'm a bit stuck.
Can anyone provide any advice about how to acheive this?
Have a good read of the Pattern Guide, in particular Pattern Guide 07: Value Conversions. It's a good tutorial. It will tell you that these magical conversions are not used everywhere in SuperCollider, but only when you use Event-based scheduling such as Patterns (e.g. your Pbind). The value conversions are actually defined in "the default Event", as described further in that tutorial article.
One consequence of all of this is that, if you want to launch just one note but you still want value conversions, you can do it with the Event style of playing notes, which creates an event using () and then calls .play on it:
~synth = (instrument: \default, scale: [0,2,4,5,7,9,11], degree: 12.rand, amp: 0.5).play;
~synth = (instrument: \default, scale: [0,3,6,9], degree: 12.rand, amp: 0.5).play;
This still returns a Synth object.
See the Event helpfile for more on this way of doing it.

Why does the locator look semi-transparent in this Dynamic graphic?

I want a position a locator on a graphic, and update its position based on the mouse position. Here is some sample code:
Show[{
Graphics[{Yellow, Rectangle[]}],
Graphics[Dynamic[
With[{pt = MousePosition[{"Graphics", Graphics}]},
{ If[pt===None, ,Locator[pt^2]], Text[pt, {0,0}, {-1,-1}] }
]
]]
}, PlotRange -> {{-.2, 1.2},{-.2, 1.2}}]
The weird thing is that sometimes the locator displays normally, sometimes it displays at what looks like half opacity. It flips from normal to half-opacity as I move the mouse around.
Why is this, and what can I do to fix it?
I'm using Mathematica 8 on OSX.

Resources