我正在为Google Visualization / Charts API开发一个基于Dart的包装器,可以在github处查看。我为所有可用的图表创建了一个特定于图表的包装类。
现在我正在调查基础类的事件。问题是所有图表中都存在不的各种事件。因此,我需要找到一种方法将特定事件类型分配给相应的图表。我已经做的是:
我为Events api创建了一个包装器:
abstract class Events {
static JsObject addListener(source_visualization, event_name, Function handling_function) {
return vis['events'].callMethod('addListener', [source_visualization, event_name, new JsFunction.withThis(handling_function)]);
}
static JsObject addOneTimeListener(source_visualization, event_name, handling_function(e)) {
return vis['events'].callMethod('addOneTimeListener', [source_visualization, event_name, new JsFunction.withThis(handling_function)]);
}
static void removeListener(listener_handler) {
return vis['events'].callMethod('removeListener', [listener_handler]);
}
/// TODO(rh): removeAllListeners
}
我创建了一个wrapper class,它封装了一个事件的所有代码。代码如下所示:
class EventWrapper<E extends Event> {
JsObject _jsChart;
String _eventName;
JsObject _handler;
Stream<E> get onEvent => _streamController.stream;
StreamController<E> _streamController;
...
EventWrapper(this._jsChart, this._eventName, E reviver(p)) {
_streamController = new StreamController.broadcast(onListen: () => _onListen(_eventName), onCancel: () => _onCancel(_eventName));
}
void _onListen(String event) {
_handler = Events.addListener(_jsChart, event, ...);
}
void _onCancel(String event) {
Events.removeListener(_handler);
}
}
在图表中,您可以使用以下代码:
class PieChart ... {
Stream<SelectEvent> get onSelect => _selectEventHandler.onEvent;
EventWrapper _selectEventHandler;
PieChart(Element e) : super._(e, "PieChart", vis) {
_selectEventHandler = new EventWrapper<SelectEvent>(jsChart, 'select', (p) => new SelectEvent());
// Other Events
}
// ...
}
问题是以下:Events
接口需要source_visulization
参数,即我想要注册事件的图表。但是当我使用dart:js
时,这仅在我在图表上调用构造函数后才可用,因为这会通过JsObject
(jsChart = new JsObject(ctx[chartName], [element])
)创建对象。通常我会在构造函数中创建EventWrapper
个实例,但由于我必须使用几个类中的事件,我想到了另外两个解决方案,而不是当前在#3上看到的。
创建一个mixin - 这不起作用,因为我没有构造函数而且我无法指定instsance方法,因为它给了我一个错误:
abstract class SelectEventMixin {
Stream<SelectEvent> get onSelect => _selectEventHandler.stream;
final StreamController _selectEventHandler = new StreamController.broadcast(onListen: _onListen);
void _onListen() {
// jsChart is available here
}
}
为每个看到的事件组合创建BaseClasses,这将允许我共享最常用的代码。一些BaseClasses将是:NoEvents
,SelectEvent
,SelectReadyEvents
,SelectReadyAnimationFinishEvents
,...
你们中有谁有更好的解决方案吗?或者有人可以告诉我如何解决我的问题#1? #2已经是最好的解决方案吗?因为我只需要组合几种方法,只有一些重复的代码?