How to delegate third-party components in react-native ios - react-native

I have following react native component in android.
parent class contains some common settings,
and some template code (eg. setData).
android version
parent component
public abstract class ParentComponent<T extends Chart, U extends Entry> extends SimpleViewManager {
#ReactProp(name = "commonSettings")
public void setCommonSettings(T chart, ReadableMap propMap) {
// do common settings
}
abstract U createEntry(ReadableMap value);
#ReactProp(name = "data")
public void setData(Chart chart, ReadableArray values) {
for (int i = 0; i < values(); i++) {
chart.addEntry(values.getMap(i));
}
}
}
child component A
public class FooComponent extends ParentComponent<FooChart, FooEntry> {
#Override
public String getName() {
return "FooChart";
}
#Override
protected View createViewInstance(ThemedReactContext reactContext) {
return new FooChart(reactContext);
}
#ReactProp(name = "fooSettings")
public void setFooSettings(FooChart chart, ReadableMap propMap) {
// do foo settings
}
#Override
FooEntry createEntry(ReadableMap value) {
return xxxxx;
}
}
child component B
public class BarComponent extends ParentComponent<BarChart, BarEntry> {
#Override
public String getName() {
return "BarChart";
}
#Override
protected View createViewInstance(ThemedReactContext reactContext) {
return new BarChart(reactContext);
}
#ReactProp(name = "barSettings")
public void setBarSettings(FooChart chart, ReadableMap propMap) {
// do foo settings
}
#Override
BarEntry createEntry(ReadableMap value) {
return xxxxx;
}
}
But How should I implement these in ios?
I am quite new to oc & swift developing, here are my doubts.
In ios, there need a RCTViewManager that return a UIView instance.
what shoud be the UIView instance?
I don't want to inherit FooChart & BarChart, delegate is what I need.
So should I create a custom UIView, initialize a fooChart and holds its reference, then self.addSubView(fooChart) ?
How to share the common settings and template code? Extension ?
Do I have to duplicate RCT_EXPORT_VIEW_PROPERTY(commonSettings, NSDictionary) in both FooChartViewManager and BarChartViewManager?
I tried to define class ParentComponentManagerSwift: RCTViewManager,
and declare RCT_EXPORT_VIEW_PROPERTY(commonSettings, NSDictionary) there,
and class FooComponentManagerSwift: ParentComponentManager, but it doesn't work.
But our components do inherit bunch of exports like backgroundColor/width/height which declared in RCTViewManager?

1) If FooChart & BarChart is a subclass of UIView, then you can initialize FooChart & BarChart, set delegate and return it directly
- (UIView *)view {
FooChart *chart = [FooChart new];
chart.delegate = self;
return chart;
}
2) You can share common settings and template code using inheritance
3) You can either duplicate exports or create some macros that will combine common exports.
Components actually do not inherit exports. All components have RCTViewManager exports + own exports, but its done without using inheritance.

Related

Showing link inside custom hover (Eclipse plugin development)

I have a custom hover inside CDT editor (see the linked SO question) and now I want to show link inside my IAnnotationHover hover:
public class MyAwesomeHover implements IAnnotationHover {
#Override
public String getHoverInfo(ISourceViewer sw, int ln) {
return "<a href='www.stackoverflow.com'>so</a>"
}
}
Unfortunately the link is not shown - the hover window shows only simple text (i.e "so"). Other HTML elements I tried work OK (ul, li, p, font ...). Can anyone help me please?
As was mentioned in the comments, the RevisionHover was a good starting point. The magic is in implementing the IAnnotationHoverExtension and creation of a custom AbstractReusableInformationControlCreator. I am posting a code snippet with solution that worked for me.
public class MyHover implements IAnnotationHover, IAnnotationHoverExtension {
...
#Override
public IInformationControlCreator getHoverControlCreator() {
return new MyCreator();
}
...
#Override
public Object getHoverInfo(ISourceViewer sv, ILineRange lr, int vnl) {
return "<a href='www.stackoverflow.com'>so</a>";
}
...
private final class MyCreator extends AbstractReusableInformationControlCreator {
protected IInformationControl doCreateInformationControl(Shell parent) {
BrowserInformationControl control =
new BrowserInformationControl(
parent,
JFaceResources.DIALOG_FONT,
false);
control.addLocationListener(
new LocationAdapter() {
#Override
public void changing(LocationEvent ev) {
if (ev.location.startsWith("file:")) {
// !This opens the link!
openUrl(ev.location)
}
}
});
return control;
}
}
}

OOP - Override init method called in constructor

I have a simple class hierarchy of two classes. Both classes call an init-method specific to that class. Therefor the init-method is overriden in the subclass:
class A
{
public A() { this->InitHandlers(); }
public virtual void InitHandlers() { // load some event handlers here }
}
class B: public A
{
public B() { this->InitHandlers(); }
public virtual void InitHandlers() {
// keep base class functionality
A::InitHandlers();
// load some other event handlers here
// ...
}
}
I know this is evil design:
The call of an overriden method from constructor is error-prone.
B::InitHandlers() would be called twice with this setup.
But semantically it makes sense to me: I want to extend the behaviour of class A in class B by loading more handlers but still keeping the handlers loaded by class A. Further this is a task that has to be done in construction. So how can this be solved with a more robust design?
You can do something like this:
class A
{
protected boolean init = false;
public A() { this->Init(); }
public virtual void Init() {
if (!this->init) {
this->init = true;
this->InitHandlers();
}
}
public virtual void InitHandlers() {
// load some event handlers here
}
}
class B: public A
{
public B() { this->Init(); }
public virtual void InitHandlers() {
// keep base class functionality
A::InitHandlers();
// load some other event handlers here
// ...
}
}
You can see it as a design pattern template method.

Cakephp overide Controller constructer

I would to override constroller constrcuter's like this :
class XControler extends AppController {
public $attr = null;
public __construct(){
$this->attr = new YController();
}
}
But when I do that I take error ! can you explain me why and how I do that with out using requestAction just OOP !
thanks
Controllers are responsible for dealing with end user requests. Each controller action should have a view, and normally you would not want to access the methods from YController inside XController.
What you want to achieve can be done this way:
XController.php
App::uses('YController', 'Controller');
class XController extends AppController {
public $attr;
public $uses = array('Person');
public function __construct($request = null, $response = null) {
$this->attr = new YController();
parent::__construct($request, $response);
}
public function method1() {
// you can now call methods from YController:
$this->attr->Ymethod1();
}
}
YController.php
class YController extends AppController {
public function Ymethod1() {
// ....
}
}
However, the business logic should be inside Models or Components. This is the proper way to share methods between more controllers.
So your XController should look like:
class XController extends AppController {
public $uses = array('Model1');
public function action1() {
$this->Model1->method1();
// ....
}
}

Interface Bloated with Callbacks

Imagine the following class hierarchy:
interface IRules
{
void NotifyPickup(object pickedUp);
void NotifyDeath();
void NotifyDamage();
}
class CaptureTheFlag : IRules
{
public void NotifyPickup(Pickup pickedUp)
{
if(pickedUp is Flag)
GameOver();
}
public void NotifyDeath()
{
}
public void NotifyDamage()
{
}
}
class DeathMatch : IRules
{
public void NotifyPickup(Pickup pickedUp)
{
points++;
}
public void NotifyDeath()
{
lives--;
}
public void NotifyDamage()
{
}
}
class GameWorld
{
IRules gameMode;
public Main(IRules gameMode)
{
this.gameMode = gameMode;
}
object[] worldObjects;
public void GameLoop()
{
foreach(object obj in worldObjects)
{
// This call may have a bunch of sideeffects, like getting a pickup
// Or a player dying
// Or damage being taken
// Different game modes are interested in different events / statistics.
obj.Update();
// Stuff happens...
gameMode.NotifyDamage();
// Stuff happens...
gameMode.NotifyDeath();
}
}
}
So here I've got an interface which contains Notify* functions. These are callbacks. Different game modes are interested in different events of the game. It's not really possible to access the concrete objects creating these events because they're buried in the worldObjects array. Imagine we are adding new game modes to our game. The IRules interface will get hugely bloated, containing all the possible things a game mode may be interested in, and most calls will be stubbed! How can I prevent this?
Edit 2: Concrete example
Seems like your Process logic sends out a lot of events. If you would give these events a name, you could subscribe your observers to them.
Then it would even be possible to create a 'filtering' observer that can forward the events to any other observer (a decorator pattern):
struct Event {
enum e { A, B, /*...*/ };
e name;
};
class IEventListener {
public:
virtual void event( Event e ) = 0;
};
// an event dispatcher implementation:
using namespace std;
class EventDispatcher {
public:
typedef std::shared_ptr<IEventListener> IEventListenerPtr;
map<Event::e,vector<IEventListenerPtr>> listeners;
void event(Event e){
const vector<IEventListenerPtr> e_listeners=listeners[e.name].second;
//foreach(begin(e_listeners)
// ,end(e_listeners)
// ,bind(IEventListener::event,_1,e));
for(vector<IEventListenerPtr>::const_iterator it=e_listeners.begin()
; it!=e_listeners.end()
; ++it)
{
(*it)->event(e);
}
}
};
You program could look like this:
Main main;
EventEventDispatcher f1;
f1.listeners[Event::A].push_back(listener1);
main.listener=f1;
Note: code untested - grab the idea.
If you really want to decouple the sender from the sink, you put an event system in between. The example given here is very dedicated and lightweight, but do sure take a look at various existing implementations: Signals and Slots implemented in Qt and in Boost, the delegates from C#, ...
Apologizes if I missed something but why not use event? Basically let IController expose void Callback() method, then Main would be able subscribe any callback to own event:
class Main
{
private event EventHandler SomeEvent;
public Main(IController controller)
{
// use weak events to avoid memory leaks or
// implement IDisposable here and unsubscribe explicitly
this.SomeEvent += controller.Callback;
}
public void ProcessStuff()
{
// invoke event here
SomeEvent();
}
}
EDIT:
This is what I would do: extract each rule action into the separate interface so you just implement what you need in concrete classes, for instance CaptureTheFlag class does only PickupFlag action for now so does not need Damage/Death methods, so just mark by IPickupable and that's it. Then just check whether concrete instance supports concrete actions and proceed with execute.
interface IPickupable
{
void NotifyPickup(object pickedUp);
}
interface IDeathable
{
void NotifyDeath();
}
interface IDamagable
{
void NotifyDamage();
}
class CaptureTheFlag : IPickupable
{
public void NotifyPickup(Pickup pickedUp)
{
if (pickedUp is Flag)
GameOver();
}
}
class DeathMatch : IPickupable, IDeathable
{
public void NotifyPickup(Pickup pickedUp)
{
points++;
}
public void NotifyDeath()
{
lives--;
}
}
class GameWorld
{
public void GameLoop()
{
foreach(object obj in worldObjects)
{
obj.Update();
IPickupable pickupable = gameMode as IPickupable;
IDeathable deathable = gameMode as IDeathable;
IDamagable damagable = gameMode as IDamagable;
if (pickupable != null)
{
pickupable.NotifyPickup();
}
if (deathable != null)
{
deathable.NotifyDeath();
}
if (damagable != null)
{
damagable.NotifyDamage();
}
}
}
}
My final solution was the C# equivalent of what xtofl posted. I created a class which stored a bunch of delegates in it. These delegates started off with default values (so they would never be null) and the different concrete IRules classes could choose to overwrite them or not. This worked better than abstract or stubbed methods because it doesn't clog the interface with unrelated methods.
class GameEvents
{
public Action<Player> PlayerKilled = p => {};
public Func<Entity, bool> EntityValid = e => true;
public Action ItemPickedUp = () => {};
public Action FlagPickedUp = () => {};
}
class IRules
{
GameEvents Events { get; }
}
class CaptureTheFlag : IRules
{
GameEvents events = new GameEvents();
public GameEvents Events
{
get { return events; }
}
public CaptureTheFlag()
{
events.FlagPickedUp = FlagPickedUp;
}
public void FlagPickedUp()
{
score++;
}
}
Each rule set can choose which events it wants to listen to. The game simply calls then by doing Rules.Events.ItemPickedUp();. It's guaranteed never to be null.
Thanks to xtofl for the idea!

Adding State in Decorator Pattern

I wonder how to add state to the chain of decorators that will be available to the consumer. Given this simplified model:
abstract class AbstractPizza
{
public abstract print(...);
}
class Pizza : AbstractPizza
{
public int Size { get; set; }
public print(...);
}
abstract class AbstractPizzaDecorator
{
public Pizza:AbstractPizza;
public abstract print();
}
class HotPizzaDecorator : AbstractPizzaDecorator
{
public int Hotness { get; set; }
public print(...);
}
class CheesyPizzaDecorator : AbstractPizzaDecorator
{
public string Cheese { get; set; }
public print(...);
}
void Main()
{
BigPizza = new Pizza();
BigPizza.Size = 36;
HotBigPizza = new HotPizzaDecorator();
HotBigPizza.Pizza = BigPizza;
HotBigPizza.Hotness = 3;
HotBigCheesyPizza = new CheesyPizzaDecorator();
HotBigCheesyPizza.Pizza = HotBigPizza;
HotBigCheesyPizza.Cheese = "Blue";
HotBigCheesyPizza.print();
HotBigCheesyPizza.size = 28; // ERRRRRR !
}
Now if they all implement the print method and propagate that though the chain, it's all good. But how does that work for the state? I can't access the size property on the HotBigCheesyPizza.
What's the part that I'm missing? Wrong pattern?
Thanks for helping!
Cheers
The decorator pattern is for adding additional behavior to the decorated class without the client needing to adjust. Thus it is not intended for adding a new interface (e.g. hotness, cheese) to the thing being decorated.
A somewhat bad example of what it might be used for is where you want to change how size is calculated: you could create a MetricSizePizzaDecorator that converts the size to/from English/metric units. The client would not know the pizza has been decorated - it just calls getSize() and does whatever it needs to do with the result (for example, to calculate the price).
I would probably not use the decorator in my example, but the point is: it does not alter the interface. In fact, nearly all design patterns come down to that - adding variability to a design without changing interfaces.
one way of adding state is by using a self referential data structure (a list). but this uses the visitor pattern and does more than you probably want. this code is rewritten from A little Java, a few patterns
// a self referential data structure with different types of nodes
abstract class Pie
{
abstract Object accept(PieVisitor ask);
}
class Bottom extends Pie
{
Object accept(PieVisitor ask) { return ask.forBottom(this); }
public String toString() { return "crust"; }
}
class Topping extends Pie
{
Object topping;
Pie rest;
Topping(Object topping,Pie rest) { this.topping=topping; this.rest=rest; }
Object accept(PieVisitor ask) { return ask.forTopping(this); }
public String toString() { return topping+" "+rest.toString(); }
}
//a class to manage the data structure
interface PieManager
{
int addTopping(Object t);
int removeTopping(Object t);
int substituteTopping(Object n,Object o);
int occursTopping(Object o);
}
class APieManager implements PieManager
{
Pie p=new Bottom();
// note: any object that implements a rational version of equal() will work
public int addTopping(Object t)
{
p=new Topping(t,p);
return occursTopping(t);
}
public int removeTopping(Object t)
{
p=(Pie)p.accept(new RemoveVisitor(t));
return occursTopping(t);
}
public int substituteTopping(Object n,Object o)
{
p=(Pie)p.accept(new SubstituteVisitor(n,o));
return occursTopping(n);
}
public int occursTopping(Object o)
{
return ((Integer)p.accept(new OccursVisitor(o))).intValue();
}
public String toString() { return p.toString(); }
}
//these are the visitors
interface PieVisitor
{
Object forBottom(Bottom that);
Object forTopping(Topping that);
}
class OccursVisitor implements PieVisitor
{
Object a;
OccursVisitor(Object a) { this.a=a; }
public Object forBottom(Bottom that) { return new Integer(0); }
public Object forTopping(Topping that)
{
if(that.topping.equals(a))
return new Integer(((Integer)(that.rest.accept(this))).intValue()+1);
else return that.rest.accept(this);
}
}
class SubstituteVisitor implements PieVisitor
{
Object n,o;
SubstituteVisitor(Object n,Object o) { this.n=n; this.o=o; }
public Object forBottom(Bottom that) { return that; }
public Object forTopping(Topping that)
{
if(o.equals(that.topping))
that.topping=n;
that.rest.accept(this);
return that;
}
}
class RemoveVisitor implements PieVisitor
{
Object o;
RemoveVisitor(Object o) { this.o=o; }
public Object forBottom(Bottom that) { return new Bottom(); }
public Object forTopping(Topping that)
{
if(o.equals(that.topping))
return that.rest.accept(this);
else return new Topping(that.topping,(Pie)that.rest.accept(this));
}
}
public class TestVisitor
{
public static void main(String[] args)
{
// make a PieManager
PieManager pieManager=new APieManager();
// add some toppings
pieManager.addTopping(new Float(1.2));
pieManager.addTopping(new String("cheese"));
pieManager.addTopping(new String("onions"));
pieManager.addTopping(new String("cheese"));
pieManager.addTopping(new String("onions"));
pieManager.addTopping(new String("peperoni"));
System.out.println("pieManager="+pieManager);
// substitute anchovies for onions
int n=pieManager.substituteTopping(new String("anchovies"),new String("onions"));
System.out.println(n+" pieManager="+pieManager);
// remove the 1.2's
n=pieManager.removeTopping(new Float(1.2));
System.out.println(n+" pieManager="+pieManager);
// how many anchovies do we have?
System.out.println(pieManager.occursTopping(new String("anchovies"))+" anchovies");
}
}
I believe your component Pizza and your abstract decorator PizzaDecorator are supposed to share the same interface, that way each instance of the decorator is capable of the same operations as the core component Pizza.