What method is used to tell the canvas to redraw its self using Skiasharp.Views.iOS? - skiasharp

Technology: Xamarin.Forms, Xamarin.iOS, and C#
Problem: I'm trying to find the equivalent of SKCanvasView.InvalidateSurface() using Skiasharp.Views.Forms to Skiasharp.Views.iOS. It appears that there is no equivalent. Below the comment in my code snippet is the method I am trying to find an equivalent for in Skiasharp.Views.iOS.
using System;
using System.Diagnostics;
using Xamarin.Forms;
using SkiaSharp;
using SkiaSharp.Views.Forms;
namespace SkiaSharpFormsDemos.Basics
{
public class ExpandingCirclesPage : ContentPage
{
protected override void OnAppearing()
{
base.OnAppearing();
pageIsActive = true;
stopwatch.Start();
Device.StartTimer(TimeSpan.FromMilliseconds(50), () =>
{
t = (float)(stopwatch.Elapsed.TotalMilliseconds % cycleTime / cycleTime);
/*
* What's the equivalent of
* SKCanvasView.InvalidateSurface()
* using Skiasharp.Views.Forms to
* Skiasharp.Views.iOS.
*/
canvasView.InvalidateSurface();
if (!pageIsActive)
{
stopwatch.Stop();
}
return pageIsActive;
});
}
}

Use iOS native UIView.SetNeedsDisplay method on the SKCanvasView instance. This should raise PaintSurface event and redraw the view.

Related

AspNetCore RazorEngine will not use FileProviders configured in derived IOptions<RazorViewEngineOptions>

Use Case
A separated template engine that doesn't interfere in any way with normal Razor operation in an AspNetCore (2.X) web app.
Problem
Whilst trying to implement the above, I've created a whole bunch of derived wrapper classes based on RazorViewEngine, RazorViewCompilerProvider, DefaultRazorPageFactoryProvider, DefaultRazorViewEngineFileProviderAccessor and RazorViewEngineOptions in an effort that these can be registered with DI and injected whilst not having side affects in the normal Razor code path. I've succeeded except for one annoying issue, whereby I still need to configure my custom FileProvider (TemplateRepository) within the normal RazorViewEngineOptions rather than my wrapper class.
e.g. In the below code from Startup.cs, even though the file provider is specified in my custom Options object, and that is what is injected into the wrapper classes, the TemplateRepository is not called for a View request unless the second service.Configure is also included (using RazorViewEngineOptions).
services.Configure<TemplateOptions>(options =>
{
options.ViewLocationExpanders.Add(new TemplateNameExpander());
options.ViewLocationFormats.Add("{0}");
options.AreaViewLocationFormats.Add("{0}");
options.FileProviders.Clear();
options.FileProviders.Add(new TemplateRepository(new SqlConnectionFactory(configuration)));
});
services.Configure<RazorViewEngineOptions>(
options =>
{
options.FileProviders.Add(new TemplateRepository(new SqlConnectionFactory(configuration)));
});
This would suggest to me that somewhere in the RazorViewEngine dependency tree the RazorViewEngineOptions is being injected somewhere, but I cannot find it.
Full Source # GitHub
It seems that you have defined your custom RazorViewEngine but you do not tell MVC to use it.
Try to add below codes to add TemplateRazorEngine to MVC view engine.
services.Configure<TemplateOptions>(options =>
{
options.ViewLocationExpanders.Add(new TemplateNameExpander());
options.ViewLocationFormats.Add("{0}");
options.AreaViewLocationFormats.Add("{0}");
options.FileProviders.Clear();
options.FileProviders.Add(new TemplateRepository(new SqlConnectionFactory(configuration)));
});
services.Configure<MvcViewOptions>(options => {
var engine = services.BuildServiceProvider().GetRequiredService<TemplateRazorEngine>();
options.ViewEngines.Add(engine);
});
Late to the party but maybe you will use this in the future. I've also tried a lot of options and in the end I came to the conclusion that child containers would solve my particular issue. Unfortunately the AspNetCore container doesn't support them so I had to implement something quick that might not work in your case. Another option would be to use StructureMap or any other container that supports this functionality.
public class ChildServiceProvider : IServiceProvider, IDisposable
{
private readonly IServiceProvider _child;
private readonly IServiceProvider _parent;
public ChildServiceProvider(IServiceProvider parent, IServiceProvider child)
{
_parent = parent;
_child = child;
}
public ChildServiceProvider(IServiceProvider parent, IServiceCollection services)
{
_parent = parent;
_child = services.BuildServiceProvider();
}
public void Dispose()
{
(_child as IDisposable)?.Dispose();
}
public object GetService(Type serviceType)
{
return _child.GetService(serviceType) ?? _parent.GetService(serviceType);
}
}
And this is how I used it
public class Startup : IStartup
{
public IServiceProvider ChildServiceProvider { get; set; }
IServiceProvider IStartup.ConfigureServices(IServiceCollection services)
{
// Define a wrapper for the RazorViewEngine and it as a singleton
services.AddSingleton<CustomRazorEngine>(serviceProvider =>
{
// get the RazorViewEngine from the childContainer
var razorViewEngine = ChildServiceProvider.GetRequiredService<IRazorViewEngine>();
return new CustomRazorEngine(razorViewEngine);
});
return services.BuildServiceProvider();
}
public void Configure(IApplicationBuilder app)
{
ChildServiceProvider = CreateChildServiceProvider(app);
app.UseMvc();
}
IServiceProvider CreateChildServiceProvider(IApplicationBuilder parentApp)
{
// create the child container from the parentApp and register
// the custom RazorViewEngineOptions that you need for the isolated templating engine
// and whatever custom services that you need
var server = parentApp.ApplicationServices.GetRequiredService<IServer>();
var webHost = WebHost.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddOptions();
services.Configure<RazorViewEngineOptions>(opts =>
{
opts.FileProviders.Clear();
opts.FileProviders.Add(new CustomFileProvider());
});
services.AddMvc();
})
.Build();
return new ChildServiceProvider(parentApp.ApplicationServices, webHost.Services);
}
}
And the custom classes that you would need to implement
public class CustomFileProvider : IFileProvider
{
}
public class CustomRazorEngine
{
private readonly IRazorViewEngine _razorViewEngine;
public CustomRazorEngine(IRazorViewEngine razorViewEngine)
{
_razorViewEngine = razorViewEngine;
}
}
This was tested with dotnet 2.2 but haven't thoroughly tested it to be 100% that there are no performance issues or other hidden ones.
Also would be curious to know if you found another solution :)

Trouble creating a base ViewModel for MvvmCross 5.1.0

I'm currently diving into the world of Xamarain with the MvvmCross framework. In my current project I want to make use of a MVVM base ViewModel to be able to reuse some of my code in other ViewModels.
When trying to implement this I've ran into a problem when using the MvxViewModel which supports passing parameters between navigation.
public abstract class BaseViewModel<TParameter> : MvxViewModel, IMvxViewModel<TParameter> where TParameter : class
{
protected readonly IMvxNavigationService _navigationService;
public BaseViewModel(IMvxNavigationService navigationService)
{
_navigationService = navigationService;
}
public new abstract Task Initialize(TParameter parameter);
}
This way I'm able to use the BaseViewModel as following.
public class ExampleViewModel : BaseViewModel<ExampleParameters>
{
private ExampleParameters _parameter;
public ExampleViewModel(IMvxNavigationService navigationService) : base(navigationService)
{
}
public override Task Initialize(ExampleParameters parameter)
{
return Task.Run(() => { _parameter = parameter; });
}
}
In this situation I think this is a pretty good solution. The ExampleViewModel even tells me I need to implement the Initialize Task when I've forgotten.
Still this solution is not great in every situation. When I have ViewModel that doesn't require the passing of parameters I still need to specify a parameters object and implement the Initialize method.
public class ParameterlessViewModel : BaseViewModel<object>
{
public ParameterlessViewModel(IMvxNavigationService navigationService) : base(navigationService)
{
}
public override Task Initialize(object parameter)
{
return Task.Run(() => { });
}
}
When removing the abstract method from the BaseViewModel I wont need to implement the Initialize method but then I won't be forced to implement it when I'm creating a ViewModel that requires the passing of parameters.
The above solution is workable but I'm curious if anyone ran into this same problem and maybe has a better solution? One which is good in both situations without having to setup two BaseViewModel classes.
Kind regards,
Jop Middelkamp
The documentation for this states: https://www.mvvmcross.com/documentation/fundamentals/navigation
If you have a BaseViewModel you might not be able to inherit MvxViewModel<TParameter> or MvxViewModel<TParameter, TResult> because you already have the BaseViewModel as base class. In this case you can implement the following interface:
IMvxViewModel<TParameter>, IMvxViewModelResult<TResult> or IMvxViewModel<TParameter, TResult>
In case you use TResult you can just copy the source code into your viewmodel:
public override TaskCompletionSource<object> CloseCompletionSource { get; set; }
public override void ViewDestroy()
{
if (CloseCompletionSource != null && !CloseCompletionSource.Task.IsCompleted && !CloseCompletionSource.Task.IsFaulted)
CloseCompletionSource?.TrySetCanceled();
base.ViewDestroy();
}
Do we do the add the Interface IMvxViewModel in the base class or the device class, can you give a simple example
In this case you can implement the following interface:
IMvxViewModel<TParameter>, IMvxViewModelResult<TResult> or IMvxViewModel<TParameter, TResult>

Apply aspect to all methods/actions in a class

I'm working on an ASP.NET MVC 5, I want to log all exceptions that occurs in the controller's actions.
To accomplish this I'm creating a custom aspect using PostSharp (in a dll), there I've already created the code to write the log files, now I want that the aspect can be controller-wide (do not want to apply it by hand to all methods).
The aspect's code looks like this:
using System;
using PostSharp.Aspects;
namespace Banlinea.Ceb.Domain.Aspects
{
public class LogException : OnExceptionAspect
{
public LogException()
{
ApplyToStateMachine = true;
}
public override void OnException(MethodExecutionArgs args)
{
//Code for logging the exception
args.FlowBehavior = FlowBehavior.ThrowException;
}
}
}
Now, what I want in my controller is to do something like this:
[LogException]
public class MyController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Other()
{
return View();
}
public ActionResult Another()
{
return View();
}
}
Just decorate the class, How can I do that?
you can do this byimplementing IAspectProvider
http://doc.postsharp.net/iaspectprovider
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
Type type = (Type)targetElement;
return type.GetMethods().Select(
m => return new AspectInstance(targetElement, new LogException()) );
}
You can apply PostSharp aspects across your codebase by using a feature called attribute multicasting.
For example, when you apply a method-level aspect on a class level or assembly level, then it is automatically copied to all the methods in the corresponding class or assembly. You can additionally filter the target elements by setting the attribute properties, such as AttributeTargetTypes, AttributeTargetMemberAttributes etc.
The sample code from your question should actually work as you expect.

cocos2d-x 3.6 PhysicsJointFixed error

I am new to cococs2dx and I am working on a code involving PhysicsJointFixed. I am using cocos2d-x-3.6. I am unable to compile the code as I wrote below following the guidelines and the PhysicsTest.cpp.
My GameLayer.h looks like:
class GameLayer : public cocos2d::Layer
{
GameLayer();
virtual ~GameLayer();
virtual bool init();
static Scene* createScene();
void setPhyWorld(PhysicsWorld* world){m_world = world;}
CREATE_FUNC(GameLayer);
private:
PhysicsWorld* m_world;
ShapeSprite* _square; //ShapeSprite extends Sprite
ShapeSprite* _square1;
PhysicsJointFixed* joint;
...
}
The createScene method in GameLayer.cpp:
Scene* GameLayer::createScene()
{
auto scene = Scene::createWithPhysics();
auto layer = GameLayer::create();
layer->setPhyWorld(scene->getPhysicsWorld());
scene->addChild(layer);
return scene;
}
Then inside GameLayer::init()
bool GameLayer::init()
{
if ( !Layer::init() )
{
return false;
}
...
...
_square = ShapeSprite::gameSpriteWithFile("square.png");
auto squareBody = PhysicsBody::createBox(Size(200,200));
_square->setPhysicsBody(squareBody);
_square->setPosition(Vec2(_screenSize.width * 0.5f, _screenSize.height * 0.7f));
_square1 = ShapeSprite::gameSpriteWithFile("square1.png");
auto squareBody1 = PhysicsBody::createBox(Size(100,100));
_square1->setPhysicsBody(squareBody1);
_square1->setPosition(Vec2(_screenSize.width * 0.5f, _screenSize.height * 0.7f));
this->addChild(_square);
this->addChild(_square1);
joint = PhysicsJointFixed::construct(_square->getPhysicsBody(), _square1->getPhysicsBody(),Vec2(100,100));
this->getScene()->getPhysicsWorld()->addJoint(joint);
return true;
}
The code gives EXC_BAD_ACCESS error on the line
this->getScene()->getPhysicsWorld()->addJoint(joint);
because, this->getScene()->getPhysicsWorld() returns NULL.
Please advise, how can I avoid the error. Any suggestion is appreciated. Thanks in advance.
This error occurs because your custom layer is not yet added to scene during init(). One possible solution is to override onEnterTransitionDidFinish() and add the joint there. In GameLayer.h add this:
virtual void onEnterTransitionDidFinish();
And move the joint adding code to GameLayer.cpp like this:
void GameLayer::onEnterTransitionDidFinish() {
joint = PhysicsJointFixed::construct(_square->getPhysicsBody(), _square1->getPhysicsBody(),Vec2(100,100));
this->getScene()->getPhysicsWorld()->addJoint(joint);
}

Getting a list of all JADE containers

I want to get a list of all containers in the current platform. This question is similar, but the answer is obsolete and the method is by querying to the AMS agent. Is there any simpler way out than to communicate via ACL messages which I think is complex, there should be a way out to get a simple list of containers. Thanks for your help
You can achieve this by using the AMSSubscriber class and listen to the events when a container is added or removed. See sample code below:
public class myAgent extends Agent {
private ArrayList<ContainerID> availableContainers = new ArrayList<ContainerID>();
/**
* Agent initializations
**/
protected void setup() {
AMSSubscriber subscriber = new AMSSubscriber(){
protected void installHandlers(Map handlers){
EventHandler addedHandler = new EventHandler(){
public void handle(Event event){
AddedContainer addedContainer = (AddedContainer) event;
availableContainers.add(addedContainer.getContainer());
}
};
handlers.put(IntrospectionVocabulary.ADDEDCONTAINER,addedHandler);
EventHandler removedHandler = new EventHandler(){
public void handle(Event event){
RemovedContainer removedContainer = (RemovedContainer) event;
ArrayList<ContainerID> temp = new ArrayList<ContainerID>(availableContainers);
for(ContainerID container : temp){
if(container.getID().equalsIgnoreCase(removedContainer.getContainer().getID()))
availableContainers.remove(container);
}
}
};
handlers.put(IntrospectionVocabulary.REMOVEDCONTAINER,removedHandler);
}
};
addBehaviour(subscriber);
}
}
Reference: 1) Developing multi-agent systems with JADE
By Fabio Luigi Bellifemine, Giovanni Caire, Dominic Greenwood (page 111)
2) Jade API