How to draw line gradient with dynamic stop in Mapbox - mapbox-android

How can I pass a dynamic list of stop parameter to line Gradient function in Mapbox SDK for Android (kotlin)
Something like:
val stops = [stop1, stop2...stopN]
style.addLayer(new LineLayer("linelayer", "line-source").withProperties(
lineCap(Property.LINE_CAP_ROUND),
lineJoin(Property.LINE_JOIN_ROUND),
lineWidth(14f),
lineGradient(interpolate(
linear(), lineProgress(),
stops //<- How to pass a dynamic array of stops here !!!
))));
Is this possible?

The way to do that is to build an Expression using an ExpressionBuilder:
style.addLayer(new LineLayer("linelayer", "line-source").withProperties(
lineCap(Property.LINE_CAP_ROUND),
lineJoin(Property.LINE_JOIN_ROUND),
lineWidth(14f),
lineGradient(getGradient(progressPoints, colorsArray));
private fun getGradient(values:MutableList<Double>, colors:MutableList<Color>): Expression {
val lit = Expression
.ExpressionBuilder("interpolate")
.addArgument(linear())
lit.lineProgress()
for ((i, v) in values.withIndex()) {
lit.stop {
// Here add your own stops and expressions
literal(v)
rgb(
colors[i].red().toDouble(),
colors[i].green().toDouble(),
colors[i].blue().toDouble()
)
}
}
return lit.build()
}

Related

PdfCleanUpTool SetRedactionColor

Is there a way to use PdfCleanUpTool so that the RedactionColor is transparent (i.e., it çshows the color of the actual background), instead of having to choose one.
I don't know why, but using PdfCleanUpTool.CleanUp() crashed (after adding the locations). However, this did the job (PdfCleaner.AutoSweepCleanUp):
public static void RemoveTexts(PdfDocument pdfDoc, List<Regex> regexes)
{
CompositeCleanupStrategy strategy = new CompositeCleanupStrategy();
foreach (Regex rgx in regexes)
{
RegexBasedCleanupStrategy rbCS = new RegexBasedCleanupStrategy(rgx);
rbCS.SetRedactionColor(null);
strategy.Add(rbCS);
}
PdfCleaner.AutoSweepCleanUp(pdfDoc, strategy);
}

Is expression evaluated differently in watch window to in the code execution

I have the following code which will check if a List<int> is compatible with type IEnumerable<object>. Covariance does not apply to value types, so this expression should evaluate to false.
public class WatchWindowTests
{
[Fact]
public void WhenRun_WillEvalueToFalseInCode_AndTrueInWatchWindow()
{
object listOfInts = new List<int>();
var x = false;
// This line evaluates to false - covariance does not apply to value types
if(listOfInts is IEnumerable<object>)
{
// This line is never executed
x = true;
}
Assert.False(x);
}
}
In the code above, the code will not enter the if block, as expected. However, in the watch window, the same expression will evaluate to true. (See image.)
Is there a reason for this, or is there a bug in Visual Studio? (I'm using Visual Studio 2022 17.0.4)

programmatically detect rendering mode in p5js?

for the p5js rendering engine, if in setup() function I use WEBGL vs P2D, how can I know later in my code what rendering mode I am in? I have wrote generic functions that work across 2D and 3D modes and I want the code to execute in different ways based on the rendering mode.
There probably are more straightforward and elegant ways of doing it but, in a pinch, you can read the drawingContext of the renderer used and see if it's either an instance of WebGLRenderingContext or CanvasRenderingContext2D
const webglSketch = p => {
p.setup = () => {
p.createCanvas(100, 100, p.WEBGL)
p.background('red')
console.log('WEBGL?', p._renderer.drawingContext instanceof WebGLRenderingContext)
console.log('2D?', p._renderer.drawingContext instanceof CanvasRenderingContext2D)
}
}
const twoDSketch = p => {
p.setup = () => {
p.createCanvas(100, 100)
p.background('blue')
console.log('WEBGL?', p._renderer.drawingContext instanceof WebGLRenderingContext)
console.log('2D?', p._renderer.drawingContext instanceof CanvasRenderingContext2D)
}
}
new p5(webglSketch)
new p5(twoDSketch)
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
If you're not using the instance mode, just check the _renderer global object.

Beanshell function gets called before if/else evaluation

I have created 2 BeanShell functions myFoo1 and myFoo2.
The first func should be executed with certain condition and the second function in different condition
The trouble is that in my JSR223Post Processor or BeanPost Processor
String code = ctx.getPreviousResult().getResponseCode();
if (code.contains("200") && (vars.get("abc1") != "Howdee")) {
${__BeanShell(myFoo1("print this"))}
}
else {
${__BeanShell(myFoo2("print this"))}
}
The problem is the beanShell functins myFoo1 and myFoo2 get called before the if/else evaluation.
In another words myFoo1 and myFoo2 they both get called one after another and if/else never has any effect, so it looks like Bean function calls are executed before any evaluation.
How do I get around that?
Remove ${__BeanShell( from the script and call it directly as myFoo2("print this):
String code = ctx.getPreviousResult().getResponseCode();
if (code.contains("200") && (vars.get("abc1") != "Howdee")) {
myFoo1("print this);
}
else {
myFoo2("print this);
}

event.preventDefault is unclear for me even if I understand stopImmediatePropagation and stopPropagation

event.preventDefault seems to be hard to understand to me.(this is the dark side of AS3). :)
stopImmediatePropagation - stopPropagation methods are pretty easy to understand.
Here's a test I made (which need just a copy/paste on the timeline) this may avoid You to spend too much time.
I just do not understand in which case preventDefault may be useful...
If you have some suggestions or links, please could You give me some feedback?
Here is the code :
// This example is coded on the Timeline.
// The Stage must fit 550 * 400 pixels (default size).
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
// function to create a MovieClip and return it to a variable.
function createMC(target:DisplayObjectContainer):MovieClip{
var mc:MovieClip = new MovieClip();
target.addChild(mc);
return mc;
}
// function that draws a Rectangle in the MovieClip of your choice.
function dRect(target:MovieClip,x:uint,y:uint,width:uint,height:uint,color:uint,alpha:Number):void{
var g:Graphics = target.graphics;
g.lineStyle(1,0x000000);
g.beginFill(color,alpha);
g.drawRect(x-width/2,y-height/2,width,height);
g.endFill();
}
// event function that trace the properties of the Event.
function traceTarget(me:MouseEvent):void{
trace(" *** event.phase = " + me.eventPhase + ", event.bubbles = " + me.bubbles);
trace("me.target.name = " + me.target.name);
trace("me.currentTarget.name(the listening object) = " + me.currentTarget.name);
/*
Use preventDefault and the events for m1 AND this will be triggered.
MOUSE_DOWN,setText will be called 2 times 1 time for this, the second time for m1!
MOUSE_DOWN,traceTarget will be called 2 times 1 time for this, the second time for m1!
*/
//me.preventDefault();
/*
Use stopPropagation to avoid that the same function is not called if an event occurs.
MOUSE_DOWN,setText will be called !
*/
me.stopPropagation();
/*
Use stopImmediatePropagation to avoid all the functions that another listener may trigger.
MOUSE_DOWN,setText WILL NEVER BE CALLED because traceTarget has been called!
stopImmediatePropagation will only allow the first listener (traceTarget).
*/
//me.stopImmediatePropagation();
trace(me.toString());
// trace the Event that is triggered.
}
function setText(me:MouseEvent):void{
tf_1.text = "me.target.name = " + me.target.name;
tf_1.setTextFormat(tf);
countText++;
trace("setText("+ me.target + ") has been called " + countText + " time(s)");
countText = 0;
}
/*
A counter to see how many times an Event method is triggered
*/
var countText:uint = 0;
/*
Declare a TextField
*/
var tf_1:TextField = new TextField();
this.addChild(tf_1);
tf_1.width = 300;
tf_1.height = 20;
tf_1.x = this.stage.stageWidth - this.stage.stageWidth/2 - tf_1.width/2;
tf_1.y = 30;
var tf:TextFormat = new TextFormat(null,16,0xff0000,true,null,null,null,null,TextFormatAlign.CENTER)
tf_1.text = "Click on a Square/Rectangle";
tf_1.setTextFormat(tf);
/*
Declare 4 MovieClips
3 MovieClips inside each other
- m1 on "this" (root1 in this case).
- m2 inside m1
- m3 inside m2
1 MovieClip on "this" (root1 in this case).
*/
var m1:MovieClip
var m2:MovieClip
var m3:MovieClip
var otherClip:MovieClip
// Create the MovieClips
m1 = createMC(this);
m2 = createMC(m1);
m3 = createMC(m2);
otherClip = createMC(this);
// set the names for the MovieClip's
m1.name = "movieClip_1";
m2.name = "movieClip_2";
m3.name = "movieClip_3";
otherClip.name = "otherClip";
// Draw Rectangles in the MovieClip's
dRect(m1,275,200,100,100,0xff0000,1);
dRect(m2,275,200,50,50,0x00ff00,1);
dRect(m3,275,200,25,25,0x0000ff,1);
dRect(otherClip,100,200,50,50,0xff9900,1);
// Add a listener on m1 MovieClip.
m1.addEventListener(MouseEvent.MOUSE_DOWN,traceTarget,false);
m1.addEventListener(MouseEvent.MOUSE_DOWN,setText,false);
// Add a listener on root (root1 in this case).
this.addEventListener(MouseEvent.MOUSE_DOWN,traceTarget,false);
this.addEventListener(MouseEvent.MOUSE_DOWN,setText,false);
If You could help me to understand the preventDefault method, I should be really happy.
Best regards. Nicolas.
From the documentation of preventDefault()
Many events have associated behaviors that are carried out by default. For example, if a user types a character into a text field, the default behavior is that the character is displayed in the text field. Because the TextEvent.TEXT_INPUT event's default behavior can be canceled, you can use the preventDefault() method to prevent the character from appearing.
Here's an example for that:
package
{
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.display.Sprite;
import flash.events.TextEvent;
public class Main extends Sprite
{
public function Main()
{
var tf:TextField = new TextField();
tf.type = TextFieldType.INPUT;
tf.border = true;
addChild(tf);
tf.addEventListener(TextEvent.TEXT_INPUT, onInput);
}
private function onInput(te:TextEvent):void
{
te.preventDefault();
}
}
}
The TextField is there, but you cannot type into it. If you comment out the line that adds the listener, the default behaviour is not prevent and you can type.
stopImmediatePropagation(), stopPropagation() and eventPhase are all concerned with the event flow: the three phases of capturing, target and bubbling. As such, they can be used to influence if an Event "reaches" an object that added a listener for it. If you want to think about the listeners that you add for an event as custom behaviour, you might call the three above "preventCustom()".
The documentation of the two methods explicitely mentions this:
Note: This method does not cancel the behavior associated with this event; see preventDefault() for that functionality.
preventDefault() deals with the default behaviour associated with the event and has nothing to do with the event flow.
As an example, you might be thinking that you could achieve the same thing as the above example by adding a listener for the capturing phase at stage and then stopping the propagation, like so:
package
{
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.display.Sprite;
import flash.events.TextEvent;
public class Main extends Sprite
{
public function Main()
{
var tf:TextField = new TextField();
tf.type = TextFieldType.INPUT;
tf.border = true;
addChild(tf);
stage.addEventListener(TextEvent.TEXT_INPUT, onInput, true); // new: added to stage and for capturing phase
}
private function onInput(te:TextEvent):void
{
te.stopImmediatePropagation(); // new: stopping propagation
}
}
}
If you execute this code, you will be able to type into the TextField just fine. Again, you're just messing with the event flow here, not the default behaviour. All you do is prevent subsequent listeners to be getting the Event, for example, if you add a listener to the TextField itself as shown below, it will never be executed, because you stop the event flow before it is reached.
package
{
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.display.Sprite;
import flash.events.TextEvent;
public class Main extends Sprite
{
public function Main()
{
var tf:TextField = new TextField();
tf.type = TextFieldType.INPUT;
tf.border = true;
addChild(tf);
tf.addEventListener(TextEvent.TEXT_INPUT, onTfInput);
stage.addEventListener(TextEvent.TEXT_INPUT, onInput, true);
}
private function onTfInput(te:TextEvent):void
{
// never executed
}
private function onInput(te:TextEvent):void
{
te.stopImmediatePropagation();
}
}
}
tl, dr;
If you find a bomb with a self timer ticking, stopImmediatePropagation() will stop other people getting notice about that and might prevent a panic, but only preventDefault() will save your life. If cancelable is false, you better run.
From the as3 docs: preventDefault() "cancels the events behaviour if that behaviour can be cancelled".
One example i can give you is the android back button. If you press the back button, it will minimize your AIR app by default. But if you listen for it and call preventDefault(). It will stop that default behavior so you can navigate to, your last open page instead.
Another example would be the home button on android, you can call preventDefault() but this action cannot he cancelled, so it will be ignored.
A mouse event like your example however, im not in a position to test what exactly that does

Resources