How do I listen to mouse clicks from RelatedItemLineMarkerInfo? - intellij-plugin

I need to run a custom action when my marker is clicked.
I tried, according to tutorial,
NavigationGutterIconBuilder<PsiElement> builder =
NavigationGutterIconBuilder.create(LessonScriptIcons.PUZZLE).
setTarget(this).
setTooltipText("Navigate to component");
RelatedItemLineMarkerInfo<PsiElement> m = builder.createLineMarkerInfo(this);
But I can't figure out how to get to the marker's navigation handler, or otherwise listen to this marker's events. (The cursor moving to the beginning of "this" element is a slightly undesired, but unimportant side effect that would be nice to suppress).
Then I tried this:
RelatedItemLineMarkerInfo marker = new RelatedItemLineMarkerInfo(this, getTextRange(), MyIcons.VOLUME, 0, tooltipProvider, handler, GutterIconRenderer.Alignment.CENTER, new ArrayList<GotoRelatedItem>());
This approach allows me to listen to the marker's mouse clicks. However, now I am experiencing a peculiar problem: whenever the marked line of code is edited, this results in duplicate, triplicate, etc. markers in the gutter.
What's the correct way to do it?

Turns out I needed to specify a pass.
int pass = Pass.UPDATE_OVERRIDEN_MARKERS;
RelatedItemLineMarkerInfo marker = new RelatedItemLineMarkerInfo(this, getTextRange(), MyIcons.VOLUME, pass, tooltipProvider, handler, GutterIconRenderer.Alignment.CENTER, new ArrayList<GotoRelatedItem>());
I had to use Pass.UPDATE_OVERRIDEN_MARKERS even though IntelliJ marked it as deprecated and said it will be removed shortly (see the link below). However, the constant recommended by IntelliJ, Pass.LINE_MARKERS, results in duplicate markers.
https://github.com/JetBrains/intellij-community/blob/master/platform/analysis-impl/src/com/intellij/codeHighlighting/Pass.java

Related

Why does NavigationView.ContainerFromMenuItem() return null except when executed from an event handler?

I am developing a WinUI3 app containing a NavigationView. The NV uses an observable collection to populate the NavigationViewItems.
The app must support expanding and collapsing NavigationViewItems programmatically. The only way I know of to do that is to set NavigationViewItem.IsExpanded = true. And the only way I know of to get the NavigationViewItem is through NavigationView.ContainerFromMenuItem().
The trouble is, ContainerFromMenuItem always returns null except when it is executed from a button event handler (such as a Click handler). The app must perform expand/collapse without user input.
For example, I have a button that launches a Click event with this code, which works just fine to toggle an NVItem:
Category selectedItem = (Category)navview.SelectedItem;
int idx1 = Categories.IndexOf(selectedItem);
var container = (NavigationViewItem)NavView.ContainerFromMenuItem(Categories[idx1]);
if (container != null)
{
container.IsExpanded = !container.IsExpanded;
}
However, that same code, when executed during app startup, such as in the MainWindow constructor after some test items are created, or in Attach(), always results in container being null.
So what am I doing wrong?
This question is somewhat similar to UWP: NavigationView.MenuItems results empty if populated programmatically but the answer to that one only deals with in-event use of ContainerFromMenuItem().
Thanks very much for any assistance on this.

How to test window scroll event with vue-testing-library?

I want to trigger user interaction for window scroll to change the isScrolled data so that the div class can change. Right now I just test the component when the isScrolled data is changed. Is this the right way to test?
This is acceptable way to test. However, instead of directly setting the isScrolled to true, call the method using the vm as (ensure that you have mocked the document.documentElement.topScroll to something other than zero):
wrapper.vm.onScrollHandler();
Finally, if you need to really test for scroll event, you can manually fire one using the dispatchEvent() method as following:
window.dispatchEvent(new CustomEvent('scroll', { detail: 'anything' }));
You use this and then run your assertion.
On a side note, instead of pictures of your code, paste actual snippets so that they are easy to copy and paste. And, you onScrollHandler can be shortened to:
onScrollHandler() {
this.isScrolled = document.documentElement.topScroll > 0;
}

videojs: How to get actual text of subtitle on 'cuechange'

I'm using videojs with some of the following code:
player.addRemoteTextTrack({ src: 'http://[somepath/to/vtt]' })
(I've verified that the Network tab in chrome shows a request to the VTT file and it's sound.)
And then:
const textTrack = player.textTracks()[0]
textTrack.addEventListener('cuechange', () => {
const activeCue = textTrack.activeCues[0]
console.log(activeCue.text, activeCue.startTime, activeCue.endTime)
})
The cuechange fires during playback, but the text attribute doesn't contain the actual subtitle text, but instead looks like the source of the .m3u8 file. The startTime and endTime of the cue seem to be correct though.
I think I'm missing something, but I'm trying to get the actual text of the triggered subtitle cue, but instead looks like this:
{"bandwidth":296728,"resolution":{"width":640,"height":268},"codecs":"avc1.42c015,mp4a.40.2","byteLength":319224,"uri":"https://...... (and so on)
Ok. Hopefully this will help someone else. It's a little confusing, but seems to be what's happening.
After I addRemoteTextTrack(), player.textTracks().length becomes 2.
One of those is of kind=metadata
The other is of kind=subtitles (the one I explicitly added)
I was listening on the kind=metadata cuechange assuming the remotely added track was the only one in the tracklist, and it fires off at the correct time in the video, even without me loading the remote text track. I think this means the stream I'm loading has some kind of metadata track for cue points embedded.
When I do add the remote track, trying to listen on the kind=subtitle track doesn't seem to fire off the cuechange event however, but I think this is because of videojs track precedence. Neither of the tracks had mode=showing, so cuechange events only fired on the one with precedence (first item in the tracklist array... the metadata one).
The solution is to simply add mode=showing to the track that I explicitly add to give it precedence:
player.addRemoteTextTrack({
src: 'http://[somepath/to/vtt]',
mode: 'showing'
})
This now allows me to listen on the tracklist item where kind=subtitle and get the actual text

How to change SpotLight shadowCameraNear parameter in THREE.js?

How do I change the shadowCameraNear and shadowCameraFar parameters of SpotLight?
In this demo, I change the shadowCameraNear parameter in the animation loop, but even though console.log() shows the change happened, the shadowCameraVisible helper object shows no change.
JSFiddle Demo
Here is the pattern you need to follow if you want to change a light's shadowCamera parameters dynamically.
light.shadowCameraNear += 0.01;
light.shadowCamera.near = light.shadowCameraNear;
light.shadowCamera.updateProjectionMatrix(); // important
updated fiddle: http://jsfiddle.net/3h8h1pzd/21/
three.js r.69

Dojo dnd (drag and drop) 1.7.2 - How to maintain a separate (non-dojo-dnd) list?

I'm using Dojo dnd version 1.7.2 and it's generally working really well. I'm happy.
My app maintains many arrays of items, and as the user drags and drops items around, I need to ensure that my arrays are updated to reflect the contents the user is seeing.
In order to accomplish this, I think I need to run some code around the time of Source.onDndDrop
If I use dojo.connect to set up a handler on my Source for onDndDrop or onDrop, my code seems to get called too late. That is, the source that's passed to the handler doesn't actually have the item in it any more.
This is a problem because I want to call source.getItem(nodes[0].id) to get at the actual data that's being dragged around so I can find it in my arrays and update those arrays to reflect the change the user is making.
Perhaps I'm going about this wrong; and there's a better way?
Ok, I found a good way to do this. A hint was found in this answer to a different question:
https://stackoverflow.com/a/1635554/573110
My successful sequence of calls is basically:
var source = new dojo.dnd.Source( element, creationParams );
var dropHandler = function(source,nodes,copy){
var o = source.getItem(nodes[0].id); // 0 is cool here because singular:true.
// party on o.data ...
this.oldDrop(source,nodes,copy);
}
source.oldDrop = source.onDrop;
source.onDrop = dropHandler;
This ensures that the new implementation of onDrop (dropHandler) is called right before the previously installed one.
Kind'a shooting a blank i guess, there are a few different implementations of the dndSource. But there are a some things one needs to know about the events / checkfunctions that are called during the mouseover / dnddrop.
One approach would be to setup checkAcceptance(source, nodes) for any target you may have. Then keep a reference of the nodes currently dragged. Gets tricky though, with multiple containers that has dynamic contents.
Setup your Source, whilst overriding the checkAcceptance and use a known, (perhaps global) variable to keep track.
var lastReference = null;
var target = dojo.dnd.Source(node, {
checkAcceptance(source, nodes) : function() {
// this is called when 'nodes' are attempted dropped - on mouseover
lastReference = source.getItem(nodes[0].id)
// returning boolean here will either green-light or deny your drop
// use fallback (default) behavior like so:
return this.inhertied(arguments);
}
});
Best approach might just be like this - you get both target and source plus nodes at hand, however you need to find out which is the right stack to look for the node in. I believe it is published at same time as the event (onDrop) youre allready using:
dojo.subscribe("/dnd/drop", function(source, nodes, copy, target) {
// figure out your source container id and target dropzone id
// do stuff with nodes
var itemId = nodes[0].id
}
Available mechanics/topics through dojo.subscribe and events are listed here
http://dojotoolkit.org/reference-guide/1.7/dojo/dnd.html#manager