Make content a class

This commit is contained in:
Patrick Walton 2012-07-12 16:32:27 -07:00
parent 8ee465cafc
commit 9b599e4e5a
2 changed files with 107 additions and 63 deletions

View file

@ -6,6 +6,7 @@
export Content; export Content;
export ControlMsg, ExecuteMsg, ParseMsg, ExitMsg; export ControlMsg, ExecuteMsg, ParseMsg, ExitMsg;
export PingMsg, PongMsg; export PingMsg, PongMsg;
export create_content;
import comm::{port, chan, listen, select2}; import comm::{port, chan, listen, select2};
import task::{spawn, spawn_listener}; import task::{spawn, spawn_listener};
@ -13,7 +14,7 @@ import io::{read_whole_file, println};
import result::{ok, err}; import result::{ok, err};
import dom::base::NodeScope; import dom::base::NodeScope;
import dom::event::ResizeEvent; import dom::event::{Event, ResizeEvent};
import dom::rcu::WriterMethods; import dom::rcu::WriterMethods;
import dom::style; import dom::style;
import gfx::renderer::Sink; import gfx::renderer::Sink;
@ -27,7 +28,7 @@ import jsrt = js::rust::rt;
import js::rust::methods; import js::rust::methods;
import js::global::{global_class, debug_fns}; import js::global::{global_class, debug_fns};
import either::{left, right}; import either::{either, left, right};
import result::extensions; import result::extensions;
type Content = chan<ControlMsg>; type Content = chan<ControlMsg>;
@ -55,70 +56,113 @@ fn join_layout(scope: NodeScope, layout: Layout) {
} }
} }
#[warn(no_non_implicitly_copyable_typarams)] class Content<S:Sink send copy> {
fn Content<S:Sink send copy>(layout: Layout, sink: S) -> Content { let sink: S;
spawn_listener::<ControlMsg>(|from_master| { let layout: Layout;
let event_port = port(); let from_master: port<ControlMsg>;
sink.add_event_listener(event_port.chan()); let event_port: port<Event>;
let scope = NodeScope(); let scope: NodeScope;
let rt = jsrt(); let jsrt: jsrt;
loop {
alt select2(from_master, event_port) {
left(ParseMsg(filename)) {
#debug["content: Received filename `%s` to parse", *filename];
// Note: we can parse the next document in parallel new(layout: Layout, sink: S, from_master: port<ControlMsg>) {
// with any previous documents. self.layout = layout;
let stream = spawn_html_lexer_task(copy filename); self.sink = sink;
let (root, style_port) = build_dom(scope, stream); self.from_master = from_master;
self.event_port = port();
// Collect the css stylesheet
let css_rules = style_port.recv();
// Apply the css rules to the dom tree:
#debug["%?", css_rules];
// Now, join the layout so that they will see the latest self.scope = NodeScope();
// changes we have made. self.jsrt = jsrt();
join_layout(scope, layout);
// Send new document and relevant styles to layout self.sink.add_event_listener(self.event_port.chan());
layout.send(BuildMsg(root, css_rules)); }
// Indicate that reader was forked so any further fn start() {
// changes will be isolated. while self.handle_msg(select2(self.from_master, self.event_port)) {
scope.reader_forked(); // Go on...
} }
}
left(ExecuteMsg(filename)) { fn handle_msg(msg: either<ControlMsg,Event>) -> bool {
#debug["content: Received filename `%s` to execute", *filename]; alt msg {
left(control_msg) {
alt read_whole_file(*filename) { ret self.handle_control_msg(control_msg);
err(msg) { }
println(#fmt["Error opening %s: %s", *filename, msg]); right(event) {
} ret self.handle_event(event);
ok(bytes) {
let cx = rt.cx();
cx.set_default_options_and_version();
cx.set_logging_error_reporter();
cx.new_compartment(global_class).chain(|compartment| {
compartment.define_functions(debug_fns);
cx.evaluate_script(compartment.global_obj, bytes, *filename, 1u)
});
}
}
}
left(ExitMsg) {
layout.send(layout_task::ExitMsg);
break;
}
right(ResizeEvent(new_width, new_height)) {
#debug("content got resize event: %d, %d", new_width, new_height);
}
} }
} }
}) }
fn handle_control_msg(control_msg: ControlMsg) -> bool {
alt control_msg {
ParseMsg(filename) {
#debug["content: Received filename `%s` to parse", *filename];
// Note: we can parse the next document in parallel
// with any previous documents.
let stream = spawn_html_lexer_task(copy filename);
let (root, style_port) = build_dom(self.scope, stream);
// Collect the css stylesheet
let css_rules = style_port.recv();
// Apply the css rules to the dom tree:
#debug["%?", css_rules];
// Now, join the layout so that they will see the latest
// changes we have made.
join_layout(self.scope, self.layout);
// Send new document and relevant styles to layout
self.layout.send(BuildMsg(root, css_rules));
// Indicate that reader was forked so any further
// changes will be isolated.
self.scope.reader_forked();
ret true;
}
ExecuteMsg(filename) {
#debug["content: Received filename `%s` to execute", *filename];
alt read_whole_file(*filename) {
err(msg) {
println(#fmt["Error opening %s: %s", *filename, msg]);
}
ok(bytes) {
let cx = self.jsrt.cx();
cx.set_default_options_and_version();
cx.set_logging_error_reporter();
cx.new_compartment(global_class).chain(|compartment| {
compartment.define_functions(debug_fns);
cx.evaluate_script(compartment.global_obj, bytes, *filename, 1u)
});
}
}
ret true;
}
ExitMsg {
self.layout.send(layout_task::ExitMsg);
ret false;
}
}
}
fn handle_event(event: Event) -> bool {
alt event {
ResizeEvent(new_width, new_height) {
#debug("content got resize event: %d, %d", new_width, new_height);
ret true;
}
}
}
} }
fn create_content<S: Sink send copy>(layout: Layout, sink: S) -> chan<ControlMsg> {
do spawn_listener::<ControlMsg> |from_master| {
Content(layout, sink, from_master).start();
}
}

View file

@ -3,21 +3,21 @@ import task::spawn_listener;
import comm::chan; import comm::chan;
import layout::layout_task; import layout::layout_task;
import layout_task::Layout; import layout_task::Layout;
import content::{Content, ExecuteMsg, ParseMsg, ExitMsg}; import content::{Content, ExecuteMsg, ParseMsg, ExitMsg, create_content};
class Engine<S:Sink send copy> { class Engine<S:Sink send copy> {
let sink: S; let sink: S;
let renderer: Renderer; let renderer: Renderer;
let layout: Layout; let layout: Layout;
let content: Content; let content: chan<content::ControlMsg>;
new(sink: S) { new(sink: S) {
self.sink = sink; self.sink = sink;
let renderer = Renderer(sink); let renderer = Renderer(sink);
let layout = Layout(renderer); let layout = Layout(renderer);
let content = Content(layout, sink); let content = create_content(layout, sink);
self.renderer = renderer; self.renderer = renderer;
self.layout = layout; self.layout = layout;