Permalink
Browse files

Remove old version

  • Loading branch information...
1 parent dc336a8 commit dac365f0ba3089108908f004c566e61aa99866a9 @hhugo committed with Hugo Heuzard Sep 23, 2011
View
15 Makefile
@@ -1,18 +1,15 @@
-INCLUDE=-I +cairo
+CAIROOPA=-I ../cairo-opa
+INCLUDE=-I +cairo $(CAIROOPA)
LINK=--mllopt cairo.cmxa
OPB=opa-plugin-builder
OPA=opa $(OPAOPT)
-all: opawhiteboard.exe
+V2=hh.cairo.opx src/v2/client.opa src/v2/buffer.opa src/v2/main.opa
-cairo.opp: src/opacairo/cairo.ml
- $(OPB) $(INCLUDE) src/opacairo/cairo.ml -o cairo
+all: OWB-v2.exe
-opawhiteboard.exe.old:
- $(OPA) src/buffer.opa src/client.opa src/builder.opa src/main.opa -o opawhiteboard.exe
-
-opawhiteboard.exe: cairo.opp
- $(OPA) $(INCLUDE) $(LINK) cairo.opp src/opacairo/buffer.opa src/opacairo/client.opa src/opacairo/main.opa -o opawhiteboard.exe
+OWB-v2.exe:
+ $(OPA) $(INCLUDE) $(LINK) $(V2) -o OWB-v2.exe
clean:
rm -Rf *.exe _build _tracks *.log *.opp
View
12 README
@@ -1,16 +1,12 @@
Collaborative white board
BUILDING
+ you will need hh.cairo package (https://github.com/hhugo/cairo-opa)
+ set CAIROOPA makefile's variable with the directory of hh.cairo.opx file
make
LAUNCHING
- ./opawhiteboard.exe
+ ./OWB-v2.exe
(launches on port 8080)
or
- ./opawhiteboard.exe -p nnnn
-
-Once started you can start drawing with people but it will not support reloading.
-In order to do so, start a browser at the following adress:
-http://myhost:myport/i_m_a_builder
-it aims to build the image and send it back to the server.
-When we have an image manipulation library on server side, it won't be needed anymore.
+ ./OWB-v2.exe -p nnnn
View
14 resources/style.css
@@ -72,6 +72,20 @@ padding: 0px;
text-align: left;
}
+#stats {
+ float: left;
+ padding: 1Opx;
+ margin-left: 50px;
+}
+
+#stats p {
+display: block;
+width: 150px;
+margin: 0px;
+padding: 0px;
+text-align: left;
+}
+
div.source{
float: right;
padding: 10px 20px 10px 10px;
View
68 src/buffer.opa
@@ -1,68 +0,0 @@
-/* Collaborative white board
-
- Copyright (C) 2010-2011 MLstate
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- @author Hugo Heuzard
-*/
-
-/*
- * Ugly implem of buffered session/netork
- */
-
-type SessionBuffer.channel('msg) = channel(list('msg))
-
-SessionBuffer = {{
-
- make(state : 'state ,treat_msg : ('state,'msg -> Session.instruction('state))) : SessionBuffer.channel('msg)=
- ns = Session.make(state : 'state,treat_msg)
- Session.make_callback(l -> List.iter(Session.send(ns,_),l))
-
- make_send_to(session : SessionBuffer.channel('msg) ,timer : int) =
- sess = Session.make([],(l,s ->
- match s with
- | {~add} -> {set=add++l}
- | {dump} -> if l == [] then {unchanged} else do Session.send(session,l) {set=[]} ))
- do Scheduler.timer(timer, ( -> Session.send(sess,{dump})))
- Session.make_callback( add -> Session.send(sess,{~add}))
-}}
-
-type NetworkBuffer.network('a) = channel(NetworkBuffer.instruction('a))
-
-type NetworkBuffer.instruction('a) = {add: SessionBuffer.channel('a)} / {remove: SessionBuffer.channel('a)} / {broadcast: list('a)} / {dump}
-NetworkBuffer = {{
- @publish
- empty(timer : int): NetworkBuffer.network('a) =
- Set = Set_make(channel_order)
- s = Session.make_own((Set.empty,[]),
- ((chans,lst), msg, own ->
- match msg with
- | {~add} ->
- do Session.on_remove(add, (-> remove(add, own)))
- {set = (Set.add(add,chans),lst)}
- | {~remove} -> {set = (Set.remove(remove, chans),lst)}
- | {~broadcast} ->
- {set=(chans,broadcast++lst)}
- | {dump} ->
- if lst == [] then {unchanged} else do sleep(0, -> Set.iter(chan -> send(chan, lst), chans)) {set=(chans,[])}
- ))
- do Scheduler.timer(timer, ( -> Session.send(s,{dump})))
- s
-
- broadcast(message: list('a), network: NetworkBuffer.network('a)): void = send(network, {broadcast = message})
- remove(channel: SessionBuffer.channel('a), network: NetworkBuffer.network('a)): void = send(network, {remove = channel})
- add(channel: SessionBuffer.channel('a), network: NetworkBuffer.network('a)): void = send(network, {add = channel})
-
-}}
View
79 src/builder.opa
@@ -1,79 +0,0 @@
-/* Collaborative white board
-
- Copyright (C) 2010-2011 MLstate
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- @author Hugo Heuzard
-*/
-
-
-/*
- * A builder is a client that cannot draw
- * it build the image by applying other client patches
- * it send the result to the server
- */
-
-
-/*
- * Set the new state
- */
-@server
-set_state(url : string) = ignore(state.set(([],url)))
-
-
-@client
-initialize_builder(atoms) =
- match Canvas.get(#canvas) with
- | {some=canvas} ->
- match Canvas.get_context_2d(canvas) with
- | {some=ctx} ->
- do Canvas.set_line_cap(ctx, {round})
- // Session to apply patches
- dispatch(msg) =
- match msg with
- | {line=(p1,p2,color,size)} -> draw_line(ctx, p1, p2, color, size)
- | {dump} -> void
- end
- //load image if any
- do match Canvas.get_image(#initial_image) with
- | {some=img} -> Canvas.draw_image(ctx, img, 0, 0)
- | {none} -> Log.debug("draw image","empty")
- treat_msg = Session.make_callback(dispatch)
- treat_atoms = Session.make_callback(List.iter(line -> send(treat_msg,{~line}),_))
- do Session.send(treat_atoms, atoms)
- //schedule state sending
- do Scheduler.timer(1000, -> Option.iter(s -> do Log.debug("CB","set_state") set_state(s) ,Canvas.to_data_url_png(canvas)))
- NetworkBuffer.add(treat_atoms,atoms_network)
- | {none} -> Log.debug("context","error")
- end
- | {none} -> Log.debug("canvas","error")
- end
-
-
-
-build() =
- (atoms,image) = get_state()
- cur_image =
- if image == ""
- then <div onready={_ -> initialize_builder(atoms)} style="display:none;"/>
- else <img id="initial_image" onready={_ -> initialize_builder(atoms)} style="display:none;" src="{image}" />;
- <>
- <h1>Canvas builder</h1>
- <canvas id="canvas" width="{canvas_width}" height="{canvas_height}">
- <p>You cannot build this image since your browser is not compatible.</p>
- <p>Please change your browser</p>
- </canvas>
- {cur_image}
- </>
View
73 src/main.opa
@@ -1,73 +0,0 @@
-/* Collaborative white board
-
- Copyright (C) 2010-2011 MLstate
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- @author Hugo Heuzard
-*/
-
-
-import stdlib.widgets.{slider,colorpicker}
-
-/*
- * Type of line (from, to, color, size)
- */
-type line = (Dom.Dimension.t, Dom.Dimension.t, Color.color, int)
-
-/*
- * Network to broadcast line.
- * Special Network Implem to decrease the among of request
- */
-@server @publish
-atoms_network : NetworkBuffer.network(line) = NetworkBuffer.empty(333)
-
-/*
- * Internal state (list of line + image)
- * The image is build by applying patch to the previous image
- */
-@server @publish
-state = Mutable.make(([] : list(line) ,""))
-@server
-get_state() = state.get()
-
-/*
- * Initialisation of chat component
- */
-@server
-default_chat = CChat.init(CChat.default_config(Random.string(10)))
-
-/*
- * Size of the board
- */
-@both_implem
-canvas_width = 600
-@both_implem
-canvas_height = 450
-
-/*
- * Main
- */
-resources = @static_include_directory("resources")
-rule_map = Rule.of_map(resources) : Parser.general_parser(resource)
-urls = parser
- | "/" -> Resource.full_page("Play with Canvas",main(),<link rel="stylesheet" href="style.css" type="text/css"> </link>,{success}, [])
- | "/i_m_a_builder" -> html("Canvas builder", build())
- | "/style.css" -> Resource.source(@static_content("resources/style.css")(),"text/css")
- | "/" r=rule_map -> r
-
-
-server = Server.simple_server(urls)
-
-
View
68 src/opacairo/buffer.opa
@@ -1,68 +0,0 @@
-/* Collaborative white board
-
- Copyright (C) 2010-2011 MLstate
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- @author Hugo Heuzard
-*/
-
-/*
- * Ugly implem of buffered session/netork
- */
-
-type SessionBuffer.channel('msg) = channel(list('msg))
-
-SessionBuffer = {{
-
- make(state : 'state ,treat_msg : ('state,'msg -> Session.instruction('state))) : SessionBuffer.channel('msg)=
- ns = Session.make(state : 'state,treat_msg)
- Session.make_callback(l -> List.iter(Session.send(ns,_),l))
-
- make_send_to(session : SessionBuffer.channel('msg) ,timer : int) =
- sess = Session.make([],(l,s ->
- match s with
- | {~add} -> {set=add++l}
- | {dump} -> if l == [] then {unchanged} else do Session.send(session,l) {set=[]} ))
- do Scheduler.timer(timer, ( -> Session.send(sess,{dump})))
- Session.make_callback( add -> Session.send(sess,{~add}))
-}}
-
-type NetworkBuffer.network('a) = channel(NetworkBuffer.instruction('a))
-
-type NetworkBuffer.instruction('a) = {add: SessionBuffer.channel('a)} / {remove: SessionBuffer.channel('a)} / {broadcast: list('a)} / {dump}
-NetworkBuffer = {{
- @publish
- empty(timer : int): NetworkBuffer.network('a) =
- Set = Set_make(Channel.order)
- rec val own = Session.make((Set.empty,[]),
- ((chans,lst), msg ->
- match msg with
- | {~add} ->
- do Session.on_remove(add, (-> remove(add, own)))
- {set = (Set.add(add,chans),lst)}
- | {~remove} -> {set = (Set.remove(remove, chans),lst)}
- | {~broadcast} ->
- {set=(chans,broadcast++lst)}
- | {dump} ->
- if lst == [] then {unchanged} else do sleep(0, -> Set.iter(chan -> send(chan, lst), chans)) {set=(chans,[])}
- ))
- do Scheduler.timer(timer, ( -> Session.send(own,{dump})))
- own
-
- broadcast(message: list('a), network: NetworkBuffer.network('a)): void = send(network, {broadcast = message})
- remove(channel: SessionBuffer.channel('a), network: NetworkBuffer.network('a)): void = send(network, {remove = channel})
- add(channel: SessionBuffer.channel('a), network: NetworkBuffer.network('a)): void = send(network, {add = channel})
-
-}}
View
352 src/opacairo/cairo.ml
@@ -1,352 +0,0 @@
-
-
-##extern-type Canvas.surface = Cairo.image_surface
-##extern-type Canvas.ctx = Cairo.t
-
-##register create_surface : int, int -> Canvas.surface
-let create_surface width height =
- Cairo.image_surface_create Cairo.FORMAT_ARGB32 ~width ~height
-
-
-##register create : Canvas.surface -> Canvas.ctx
-let create surface =
- let ctx = Cairo.create surface in
- Cairo.set_line_width ctx 4. ;
- Cairo.set_line_join ctx Cairo.LINE_JOIN_ROUND ;
- Cairo.set_line_cap ctx Cairo.LINE_CAP_ROUND ;
- ctx
-
-##register save : Canvas.ctx -> void
-let save ctx = Cairo.save(ctx)
-
-##register restore : Canvas.ctx -> void
-let restore ctx = Cairo.save(ctx)
-
-##register to_data : Canvas.surface -> string
-let to_data surface =
- let b = Buffer.create 10000 in
- Cairo_png.surface_write_to_stream surface (Buffer.add_string b);
- Buffer.contents b
-
-##register draw : Canvas.ctx, float, float, float, float -> void
-let draw ctx x1 y1 x2 y2=
- Cairo.move_to ctx x1 y1;
- Cairo.line_to ctx x2 y2;
- Cairo.close_path ctx ;
- Cairo.stroke ctx
-
-(* Tranformations (default transform is the identity matrix) *)
-
-##register scale: Canvas.ctx, float, float -> void
-let scale c sx sy = Cairo.scale c ~sx ~sy
-
-##register rotate: Canvas.ctx, float -> void
-let rotate c angle = Cairo.rotate c ~angle
-
-##register translate: Canvas.ctx, float, float -> void
-let translate c tx ty = Cairo.translate c ~tx ~ty
-
-(* ##register transform: Canvas.ctx, int, int, int, int, int, int -> void *)
-(* let transform c xx xy yx yy x0 x0 = Cairo.transform c m *)
-
-(* ##register set_transform: Canvas.ctx, int, int, int, int, int, int -> void *)
-
-(* // compositing *)
-(* ##register set_global_alpha: Canvas.ctx, float -> void *)
-
-(* ##register get_global_alpha: Canvas.ctx -> float *)
-
-(* colors and styles *)
-
- ##register set_stroke_style_color: Canvas.ctx, float, float, float -> void
-let set_stroke_style_color c red green blue =
- Cairo.set_source_rgb c ~red ~green ~blue
-
-
-(* ##register set_stroke_style_gradient: Canvas.ctx, Canvas.gradient -> void *)
-
-(* ##register set_stroke_style_pattern: Canvas.ctx, Canvas.pattern -> void *)
-
-(* ##register set_fill_style_color: Canvas.ctx, string -> void *)
-
-(* ##register set_fill_style_gradient: Canvas.ctx, Canvas.gradient -> void *)
-
-(* ##register set_fill_style_pattern: Canvas.ctx, Canvas.pattern -> void *)
-
-(* ##register get_stroke_style: Canvas.ctx -> opa[Canvas.style] *)
-
-(* ##register get_fill_style: Canvas.ctx -> opa[Canvas.style] *)
-
-(* //Gradient *)
-
-(* ##register add_color_stop: Canvas.gradient, float, string -> void *)
-
-(* ##register create_linear_gradient: Canvas.ctx, int, int, int, int -> Canvas.gradient *)
-
-(* ##register create_radial_gradient : Canvas.ctx, int, int, int, int, int, int -> Canvas.gradient *)
-
-(* //pattern *)
-
-(* ##register create_pattern_i \ bslcanvas_create_pattern : Canvas.ctx, Image.image, string -> Canvas.pattern *)
-(* ##register create_pattern_v \ bslcanvas_create_pattern : Canvas.ctx, Video.video, string -> Canvas.pattern *)
-(* ##register create_pattern_c \ bslcanvas_create_pattern : Canvas.ctx, Canvas.canvas, string -> Canvas.pattern *)
-(* function bslcanvas_create_pattern(ctx, image, repeat) *)
-(* { *)
-(* ctx.createPattern(image, repeat) *)
-(* } *)
-
-(* // line caps/joins *)
-(* ##register get_line_width: Canvas.ctx -> float *)
-(* ##args(ctx) *)
-(* { *)
-(* return ctx.lineWidth *)
-(* } *)
-
-##register set_line_width \ `Cairo.set_line_width` : Canvas.ctx, float -> void
-
-(* ctx.lineWidth = size *)
-(* } *)
-
-(* ##register set_line_cap: Canvas.ctx, string -> void *)
-(* ##args(ctx, cap) *)
-(* { *)
-(* ctx.lineCap = cap *)
-(* } *)
-
-(* ##register get_line_cap: Canvas.ctx -> string *)
-(* ##args(ctx) *)
-(* { *)
-(* return ctx.lineCap *)
-(* } *)
-
-(* ##register set_line_join: Canvas.ctx, string -> void *)
-(* ##args(ctx, join) *)
-(* { *)
-(* ctx.lineJoin = join *)
-(* } *)
-
-(* ##register get_line_join: Canvas.ctx -> string *)
-(* ##args(ctx) *)
-(* { *)
-(* return ctx.lineJoin *)
-(* } *)
-
-(* ##register set_miter_limit: Canvas.ctx, float -> void *)
-(* ##args(ctx, limit) *)
-(* { *)
-(* ctx.miterLimit = limit *)
-(* } *)
-
-(* ##register get_miter_limit: Canvas.ctx -> float *)
-(* ##args(ctx) *)
-(* { *)
-(* return ctx.miterLimit *)
-(* } *)
-(* // shadows *)
-
-(* ##register set_shadow_color: Canvas.ctx, string -> void *)
-(* ##args(ctx,color) *)
-(* { *)
-(* ctx.shadowColor=color *)
-(* } *)
-
-(* ##register get_shadow_color: Canvas.ctx -> string *)
-(* ##args(ctx) *)
-(* { *)
-(* return ctx.shadowColor *)
-(* } *)
-
-(* ##register set_shadow_offset_x: Canvas.ctx, int -> void *)
-(* ##args(ctx,offset) *)
-(* { *)
-(* ctx.shadowOffsetX=offset *)
-(* } *)
-
-(* ##register get_shadow_offset_x: Canvas.ctx -> int *)
-(* ##args(ctx) *)
-(* { *)
-(* return ctx.shadowOffsetX *)
-(* } *)
-
-(* ##register set_shadow_offset_y: Canvas.ctx, int -> void *)
-(* ##args(ctx,offset) *)
-(* { *)
-(* ctx.shadowOffsetY=offset *)
-(* } *)
-
-(* ##register get_shadow_offset_y: Canvas.ctx -> int *)
-(* ##args(ctx) *)
-(* { *)
-(* return ctx.shadowOffsetY *)
-(* } *)
-
-(* ##register set_shadow_blur: Canvas.ctx, int -> void *)
-(* ##args(ctx,blur) *)
-(* { *)
-(* ctx.shadowBlur=blur *)
-(* } *)
-
-(* ##register get_shadow_blur: Canvas.ctx -> int *)
-(* ##args(ctx) *)
-(* { *)
-(* return ctx.shadowBlur *)
-(* } *)
-
-(* // rects *)
-(* ##register clear_rect: Canvas.ctx, int ,int, int, int -> void *)
-(* ##args(ctx,x,y,w,h) *)
-(* { *)
-(* ctx.clearRect(x, y, w, h) *)
-(* } *)
-
-(* ##register fill_rect: Canvas.ctx, int ,int, int, int -> void *)
-(* ##args(ctx,x,y,w,h) *)
-(* { *)
-(* ctx.fillRect(x, y, w, h) *)
-(* } *)
-
-(* ##register stroke_rect: Canvas.ctx, int ,int, int, int -> void *)
-(* ##args(ctx,x,y,w,h) *)
-(* { *)
-(* ctx.strokeRect(x, y, w, h) *)
-(* } *)
-
-(* // path API *)
-(* ##register begin_path: Canvas.ctx -> void *)
-(* ##args(ctx) *)
-(* { *)
-(* ctx.beginPath() *)
-(* } *)
-
-
-(* ##register close_path: Canvas.ctx -> void *)
-(* ##args(ctx) *)
-(* { *)
-(* ctx.closePath() *)
-(* } *)
-
-(* ##register move_to: Canvas.ctx, int, int -> void *)
-(* ##args(ctx, x, y) *)
-(* { *)
-(* ctx.moveTo(x, y) *)
-(* } *)
-
-(* ##register line_to: Canvas.ctx, int, int -> void *)
-(* ##args(ctx, x, y) *)
-(* { *)
-(* ctx.lineTo(x, y) *)
-(* } *)
-
-(* ##register quadratic_curve_to: Canvas.ctx, int, int, int, int -> void *)
-(* ##args(ctx, cpx, cpy, x, y) *)
-(* { *)
-(* ctx.quadraticCurveTo(cpx, cpy, x, y) *)
-(* } *)
-
-(* ##register bezier_curve_to: Canvas.ctx, int, int, int, int, int, int -> void *)
-(* ##args(ctx, cp1x, cp1y, cp2x, cp2y, x, y) *)
-(* { *)
-(* ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) *)
-(* } *)
-
-(* ##register arc_to: Canvas.ctx, int, int, int, int, int -> void *)
-(* ##args(ctx, x1, y1, x2, y2, radius) *)
-(* { *)
-(* ctx.arcTo( x1, y1, x2, y2, radius) *)
-(* } *)
-
-(* ##register rect: Canvas.ctx, int, int, int, int -> void *)
-(* ##args(ctx, x, y, w, h) *)
-(* { *)
-(* ctx.rect( x, y, w, h) *)
-(* } *)
-
-(* // ##register arc: Canvas.ctx, int, int, int, int -> void *)
-(* // ##args(ctx, x, y, w, h) *)
-(* // { *)
-(* // ctx.rect( x, y, w, h) *)
-(* // } *)
-
-(* ##register fill: Canvas.ctx -> void *)
-(* ##args(ctx) *)
-(* { *)
-(* ctx.fill() *)
-(* } *)
-
-(* ##register stroke: Canvas.ctx -> void *)
-(* ##args(ctx) *)
-(* { *)
-(* ctx.stroke() *)
-(* } *)
-
-(* ##register clip: Canvas.ctx -> void *)
-(* ##args(ctx) *)
-(* { *)
-(* ctx.clip() *)
-(* } *)
-
-(* ##register is_point_in_path : Canvas.ctx, int, int -> bool *)
-(* ##args(ctx, x, y) *)
-(* { *)
-(* return ctx.isPointInPath(x, y) *)
-(* } *)
-
-(* // focus management *)
-(* //todo *)
-
-(* // text *)
-(* //todo *)
-
-(* // drawing images *)
-
-(* ##register create_image : string -> Image.image *)
-(* ##args(data) *)
-(* { *)
-(* var img = new Image(); *)
-(* img.src = data; *)
-(* return img *)
-(* } *)
-
-(* ##register draw_image_i \ bslcanvas_draw_image: Canvas.ctx, Image.image, int, int -> void *)
-(* ##register draw_image_c \ bslcanvas_draw_image: Canvas.ctx, Canvas.canvas, int, int -> void *)
-(* ##register draw_image_v \ bslcanvas_draw_image: Canvas.ctx, Video.video, int, int -> void *)
-(* function bslcanvas_draw_image(ctx, image, x, y) *)
-(* { *)
-(* return ctx.drawImage(image, x ,y) *)
-(* } *)
-
-(* ##register draw_image_di \ bslcanvas_draw_image_d: Canvas.ctx, Image.image, int, int, int, int -> void *)
-(* ##register draw_image_dc \ bslcanvas_draw_image_d: Canvas.ctx, Canvas.canvas, int, int, int, int -> void *)
-(* ##register draw_image_dv \ bslcanvas_draw_image_d: Canvas.ctx, Video.video, int, int, int, int -> void *)
-(* function bslcanvas_draw_image_d(ctx, image, x, y, w, h) *)
-(* { *)
-(* return ctx.drawImage(image, x ,y, w ,h) *)
-(* } *)
-
-(* ##register draw_image_fi \ bslcanvas_draw_image_f: Canvas.ctx, Image.image, int, int, int, int, int, int, int, int -> void *)
-(* ##register draw_image_fc \ bslcanvas_draw_image_f: Canvas.ctx, Canvas.canvas, int, int, int, int, int, int, int, int -> void *)
-(* ##register draw_image_fv \ bslcanvas_draw_image_f: Canvas.ctx, Video.video, int, int, int, int, int, int, int, int -> void *)
-(* function bslcanvas_draw_image_f(ctx, image, sx, sy, sw, sh, dx, dy, dw, dh) *)
-(* { *)
-(* return ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) *)
-(* } *)
-
-(* // pixel manipulation *)
-
-(* ##register put_image_data: Canvas.ctx, Image.data, int, int -> void *)
-(* ##args(ctx, data, x, y) *)
-(* { *)
-(* ctx.putImageData(data, x ,y) *)
-(* } *)
-
-(* //other *)
-
-
-(* ##register get_image : Dom.private.element -> opa[option(Image.image)] *)
-(* ##args(dom) *)
-(* { *)
-(* if (dom && dom[0] && (dom[0].tagName.toLowerCase() == "img") && dom[0].complete){ *)
-(* return js_some(dom[0]) *)
-(* } *)
-(* return js_none *)
-(* } *)
View
256 src/opacairo/client.opa
@@ -1,256 +0,0 @@
-/* Collaborative white board
-
- Copyright (C) 2010-2011 MLstate
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- @author Hugo Heuzard
-*/
-
-import stdlib.widgets.core
-import stdlib.components.chat
-import stdlib.web.mail
-
-/*
- * Create a client session to send new line to the server
- * Special session implem to decrease the amount of request
- * This will send messages to the server a most every 250 ms
- */
-@client
-atoms_sess : channel(list(line))=SessionBuffer.make_send_to(Session.make_callback(l -> NetworkBuffer.broadcast(l,atoms_network)),250)
-
-/*
- * Send a line to the server
- */
-@client
-send_line(p1, p2, color : Color.color, size : int) : void =
- Session.send(atoms_sess,[(p1, p2, color, size)])
-
-
-@client
-_ =
- info = Session.make_callback((nb : int,dist: int) ->
- Dom.transform([
- #nb_user <- nb,
- #distance <- dist]))
- do register_to_server(info)
- void
-@server @publish
-register_to_server(info)=
- _ = Session.on_remove(info, ->
- do println("client disconnected")
- Session.send(dist,{rem}))
- _ = Session.send(dist,{new})
- _ = Network.add(info, count_client_distance)
- void
-/*
- * Draw a line into the canvas
- */
-@client
-draw_line(ctx, p1, p2, color : Color.color, size : int) : void =
- do Canvas.begin_path(ctx);
- do Canvas.set_line_width(ctx, Int.to_float(size))
- do Canvas.set_stroke_style(ctx, {~color})
- do Canvas.move_to(ctx,p1.x_px,p1.y_px)
- do Canvas.line_to(ctx,p2.x_px,p2.y_px)
- do Canvas.stroke(ctx)
- Canvas.close_path(ctx)
-
-/*
- * Initialize the client when ready
- */
-@client
-initialize_client(atoms) =
- id = Random.string(10)
- //get canvas
- match Canvas.get(#canvas) with
- | {some=canvas} ->
- //get context
- match Canvas.get_context_2d(canvas) with
- | {some=ctx} ->
- //set canvas style
- do Canvas.set_line_cap(ctx, {round})
-
- //Session store canvas state
- dispatch((pos,color,size), msg ) =
- match msg with
- | {~set_size} -> {set=(pos,color,set_size)} //change cursor size
- | {~set_color} -> {set=(pos,set_color,size)} //change color
- | {~set_pos} -> {set=(set_pos,color,size)} //change positon
- | {~move} -> //move to the new positon
- //do Log.info("change_size","{size}")
- do draw_line(ctx, pos,move,color,size)
- do send_line(pos,move,color,size)
- {set=(move,color,size)}
- | {line=(p1,p2,color,size)} -> //draw a line
- do draw_line(ctx, p1, p2, color, size)
- {unchanged}
- end
- slider_size = 5
- treat_msg = Session.make(({x_px=0 y_px=0},Color.black,slider_size), dispatch)
- treat_atoms = Session.make_callback( atoms -> List.iter(atom -> Session.send(treat_msg,{line=atom}),List.rev(atoms)))
- // add drawing tools
- // color picker
- style_colorpick ={ thumb = WStyler.make_class(["cp_thumb"])
- thumb_dragged = WStyler.make_class(["cp_thumb_dragged"])
- thumb_over = WStyler.make_class(["cp_thumb_over"])
- gauge = WStyler.make_class(["cp_gauge"])
- cursor = WStyler.make_class(["cp_cursor"])
- preview = WStyler.make_class(["cp_preview"])
- }
- config_colorpicker = {WColorpicker.default_config with style=style_colorpick size = (256,256) on_select= c -> Session.send(treat_msg, {set_color=c}) display = {full}}
- colorpicker = WColorpicker.html("{id}_color", config_colorpicker)
-
- //slider
- style_slider = { thumb = WStyler.make_class(["thumb"])
- thumb_dragged = WStyler.make_class(["thumb_dragged"])
- thumb_over = WStyler.make_class(["thumb_over"])
- gauge = WStyler.make_class(["gauge"])
- }
- change_size(set_size) =
- //do Log.info("change_size","{set_size}")
- Session.send(treat_msg, {~set_size})
- config_slider = { style=style_slider on_change=change_size on_release=change_size range=(1,50) init=5 step=2}
- slider = WSlider.html(config_slider, "{id}_size")
-
- //insert drawing tools to the page
- drawing_tools = <><h4>Cursor size</h4>{slider}<h4>Color</h4>{colorpicker}</>
- _ = Dom.put_inside(#drawing_tools,Dom.of_xhtml(drawing_tools))
-
- //load the initial image if any
- do match Canvas.get_image(#initial_image) with
- | {some=img} -> do Canvas.draw_image(ctx, img, 0, 0)
- Dom.hide(#initial_image)
- | {none} -> Log.debug("draw image","empty")
- //apply patches if any
- do Session.send(treat_atoms, atoms)
- //register session to reveive updates
- do NetworkBuffer.add(treat_atoms,atoms_network)
- //Initial state
- do Session.send(treat_msg, {set_size=slider_size})
- do Session.send(treat_msg, {set_color=Color.darkblue})
-
- //function call when drawing
- start_drawing(ev)=
- set_pos = Dom.Dimension.sub(ev.mouse_position_on_page,Dom.get_offset(#canvas))
- do Session.send(treat_msg, {~set_pos})
- do Session.send(treat_msg, {move=Dom.Dimension.add(set_pos,{x_px=1;y_px=0})}) // this is a hack to draw point with some browser
- do Session.send(treat_msg, {~set_pos})
- draw(ev) =
- move = Dom.Dimension.sub(ev.mouse_position_on_page,Dom.get_offset(#canvas))
- Session.send(treat_msg,{~move})
- _ = Dom.bind(#canvas,{mousemove}, draw)
- void
- _ = Dom.bind(Dom.select_all(),{mouseup}, ( _ -> Dom.unbind_event(#canvas,{mousemove})))
- _ = Dom.bind(#canvas,{mousedown},start_drawing)
- void
- | {none} -> Log.debug("context","error")
- end
- | {none} -> Log.debug("canvas","error")
- end
-
-/*
- * Main page
- */
-
-main() =
- atoms=[]
- //chat creation
- chat=
- id = Random.string(8)
- config = CChat.default_config(id)
- initial_content = default_chat.requester({ range = (0, config.history_limit) })
- initial_display = {CChat.default_display(id, Random.string(8)) with reverse=false}
- CChat.create(config, default_chat, id, initial_display, initial_content, (_,_ -> void ) )
-
- //main content
- <>
- <div id="container">
- <div id="header">
- <div id="logo">
- <p>This is a demo application of the open source Opa technology.
- <br />
-Head to <a href="http://opalang.org">http://opalang.org</a> to learn how to program real-time, distributed, web applications.</p>
- </div>
- </div>
- <div id="content">
- <div id="canvas_wrapper" width="{canvas_width}" height="{canvas_height}" >
- <canvas id="canvas" width="{canvas_width}" height="{canvas_height}"></canvas>
- <img id="initial_image" width="{canvas_width}" height="{canvas_height}" onready={_ -> Scheduler.sleep(1000,->initialize_client(atoms))} src="img.png" />
- </div>
- <div id="drawing_tools" />
- </div>
- <div id="chat">
- <h4>Chat</h4>
- {chat}
- </div>
- <div id="sendit">
- Send this masterpiece at
- <input type="text" id="myemail" placeholder="your email here" />
- <input type="button" onclick={sendit} value="send it"/>
- <span id="sent"></span>
- </div>
- <div id="stats">
- <p> users: <span id=#nb_user /></p>
- <p> distance: <span id=#distance /></p>
- </div>
- <div class="source">Get the sources and fork on <a href="https://github.com/hhugo/OpaWhiteBoard">Github</a></div>
- </div>
- </>
-
-
-/*
- * Send image by email
- */
-
-@client
-sendit(_)=
- match Canvas.get(#canvas) with
- | {some=canvas} ->
- email = Dom.get_value(#myemail)
- img = Canvas.to_data_url_png(canvas)
- match Email.of_string_opt(email) with
- | {some=email} ->
- match img with
- | {some=img} ->
- _ = Dom.put_inside(#sent,Dom.of_xhtml(<>Sending Email... !</>))
- do Dom.set_value(#myemail,"")
- do Scheduler.sleep(2000,(-> _ = Dom.put_inside(#sent,Dom.of_xhtml(<></>)) void))
- sendit_server(email,img)
- | _ ->
- _ = Dom.put_inside(#sent,Dom.of_xhtml(<>Your browser seams too old !</>))
- _ = Scheduler.sleep(2000,(-> _ = Dom.put_inside(#sent,Dom.of_xhtml(<></>)) void))
- void
- end
- | {none} ->
- _ = Dom.put_inside(#sent,Dom.of_xhtml(<>Bad email address !</>))
- _ = Scheduler.sleep(2000,(-> _ = Dom.put_inside(#sent,Dom.of_xhtml(<></>)) void))
- void
- end
- | _ -> void
- end
-
-
-@server @publish
-sendit_server(email,img)=
- img = String.drop_left(22,img) //in order to drop "data:image/png;base64,"
- content =
- "Here is your masterpiece\n\nThanks"
- Email.try_send_with_files_async(
- Email.of_string("canvas@opalang.org"),
- email,
- "Piece of art",
- {text=content},
- [{filename="masterpiece.png" content=img encoding="base64" mime_type="image/png"}],
- (_ -> void) )
View
125 src/opacairo/main.opa
@@ -1,125 +0,0 @@
-/* Collaborative white board
-
- Copyright (C) 2010-2011 MLstate
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- @author Hugo Heuzard
-*/
-
-
-import stdlib.widgets.{slider,colorpicker}
-
-/*
- * Type of line (from, to, color, size)
- */
-type line = (Dom.Dimension.t, Dom.Dimension.t, Color.color, int)
-
-type Canvas.surface = external
-type Canvas.ctx = external
-
-/*
- * Size of the board
- */
-@both_implem
-canvas_width = 600.
-@both_implem
-canvas_height = 450.
-
-@server
-surface = (%% Cairo.create_surface %%)(Int.of_float(canvas_width),Int.of_float(canvas_height))
-context = (%% Cairo.create %%)(surface)
-
-
-
-/*
- * Network to broadcast line.
- * Special Network Implem to decrease the among of request
- */
-type info_msg =
- {new}
-/ {dump}
-/ {rem}
-/ {add:int}
-@server @publish
-atoms_network : NetworkBuffer.network(line) = NetworkBuffer.empty(333)
-@server @publish
-count_client_distance : Network.network((int,int)) = Network.empty()
-@server @publish
-dist = Session.make((0,0,false), ((nb,d,updt),msg : info_msg ->
- match msg with
- | {new} ->
- {set=(nb+1,d,true)}
- | {dump} -> do if updt
- then Network.broadcast((nb,d),count_client_distance)
- {set=(nb,d,false)}
- | {~add} -> {set=(nb,d+add,true)}
- | {rem} -> {set=(nb-1,d,false)}))
-
-do Scheduler.timer(500,-> Session.send(dist,{dump}))
-
-f(size,co,x1,y1,x2,y2) =
- dx = (x1-x2)
- dy = (y1-y2)
- d = Math.sqrt_f(Float.of_int(dx*dx + dy*dy))
- do Session.send(dist,{add=Int.of_float(d)})
- fl=Float.of_int
- flc(i)=fl(i) / 255.
- size=Float.of_int(size)
- do (%% Cairo.set_stroke_style_color %%)(context,flc(co.r),flc(co.g),flc(co.b))
- do (%% Cairo.set_line_width %%)(context,size)
- do (%% Cairo.draw %%)(context,fl(x1),fl(y1),fl(x2),fl(y2))
- void
-
-ttt : channel(list(line)) = Session.make_callback(
- l ->
- List.iter((from,to,co,size) ->
- f(size,co,from.x_px,from.y_px,to.x_px,to.y_px),
- l))
-
-do NetworkBuffer.add(ttt,atoms_network)
-
-/*
- * Initialisation of chat component
- */
-@server
-default_chat = CChat.init(CChat.default_config(Random.string(10)))
-
-/*
- * Main
- */
-resources = @static_include_directory("resources")
-rule_map = Rule.of_map(resources) : Parser.general_parser(resource)
-urls = parser
- | "/" -> Resource.full_page("Play with Canvas",main(),<link rel="stylesheet" href="style.css" type="text/css"> </link>,{success}, [])
- | "/img.png" -> Resource.dyn_image({png=(%% Cairo.to_data %%)(surface)})
- | "/style.css" -> Resource.source(@static_content("resources/style.css")(),"text/css")
- | "/" r=rule_map -> r
-
-
-server = Server.simple_server(urls)
-
-@server
-atoms_sess2 : channel(list(line)) = SessionBuffer.make_send_to(Session.make_callback(l -> NetworkBuffer.broadcast(l,atoms_network)),250)
-
-// @server
-// color_random()=
-// r()=Random.int(255)
-// {r=r() g=r() b=r() a=255}
-// @server
-// _ = Scheduler.timer(100, ->
-// rand(size) = Random.int(Int.of_float(size))
-// rand_dim() = {x_px=rand(canvas_width) y_px=rand(canvas_height)}
-
-// Session.send(atoms_sess2,[(rand_dim(), rand_dim(), color_random(), Random.int(50))]))
View
40 src/v2/buffer.opa
@@ -0,0 +1,40 @@
+/* Collaborative white board
+
+ Copyright (C) 2010-2011 MLstate
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ @author Hugo Heuzard
+*/
+
+type Buffer.msg('a) = {add:'a} / {flush:(list('a) -> void)}
+
+type Buffer.t('a) = Session.channel(Buffer.msg('a))
+
+Buffer = {{
+ make()=Session.make([],(lst,msg:Buffer.msg->
+ match msg with
+ | {~add} -> {set=[add|lst]}
+ | {~flush} ->
+ do flush(List.rev(lst))
+ {set=[]}
+ )
+ )
+
+ add(c,x) = Session.send(c,{add=x})
+
+ flush(c,k) =
+ Session.send(c,{flush=k})
+
+}}
View
0 src/opacairo/cairo.opa → src/v2/cairo.opa
File renamed without changes.
View
93 src/client.opa → src/v2/client.opa
@@ -21,25 +21,30 @@
import stdlib.widgets.core
import stdlib.components.chat
import stdlib.web.mail
+import stdlib.web.canvas
-/*
- * Create a client session to send new line to the server
- * Special session implem to decrease the amount of request
- * This will send messages to the server a most every 250 ms
- */
-@client
-atoms_sess = SessionBuffer.make_send_to(Session.make_callback(l -> NetworkBuffer.broadcast(l,atoms_network)),250)
/*
* Send a line to the server
*/
+
+@client
+client_flow : Buffer.t(line) = Buffer.make()
+
@client
send_line(p1, p2, color : Color.color, size : int) : void =
- Session.send(atoms_sess,[(p1, p2, color, size)])
+ Buffer.add(client_flow,(p1, p2, color, size))
+
+@client
+_ = Scheduler.timer(300,->
+ Buffer.flush(client_flow,(l->
+ if not(List.is_empty(l))
+ then drawing(l))))
/*
* Draw a line into the canvas
*/
+
@client
draw_line(ctx, p1, p2, color : Color.color, size : int) : void =
do Canvas.begin_path(ctx);
@@ -54,7 +59,7 @@ draw_line(ctx, p1, p2, color : Color.color, size : int) : void =
* Initialize the client when ready
*/
@client
-initialize_client(atoms) =
+initialize_client() =
id = Random.string(10)
//get canvas
match Canvas.get(#canvas) with
@@ -64,23 +69,30 @@ initialize_client(atoms) =
| {some=ctx} ->
//set canvas style
do Canvas.set_line_cap(ctx, {round})
-
//Session store canvas state
dispatch((pos,color,size), msg ) =
match msg with
+ | {metric=(nb,dist)} ->
+ do Dom.transform([
+ #nb_user <- nb,
+ #distance <- dist])
+ {unchanged}
| {~set_size} -> {set=(pos,color,set_size)} //change cursor size
| {~set_color} -> {set=(pos,set_color,size)} //change color
| {~set_pos} -> {set=(set_pos,color,size)} //change positon
| {~move} -> //move to the new positon
+ //do Log.info("change_size","{size}")
do draw_line(ctx, pos,move,color,size)
do send_line(pos,move,color,size)
{set=(move,color,size)}
| {line=(p1,p2,color,size)} -> //draw a line
do draw_line(ctx, p1, p2, color, size)
{unchanged}
end
- treat_msg = Session.make(({x_px=0 y_px=0},Color.black,5), dispatch)
- treat_atoms = Session.make_callback( atoms -> List.iter(atom -> Session.send(treat_msg,{line=atom}),List.rev(atoms)))
+ slider_size = 5
+ treat_msg = Session.make(({x_px=0 y_px=0},Color.black,slider_size), dispatch)
+ treat_lines = Session.make_callback(List.iter(line -> Session.send(treat_msg,{~line}),_))
+ treat_metric = Session.make_callback(metric -> Session.send(treat_msg,{~metric}))
// add drawing tools
// color picker
style_colorpick ={ thumb = WStyler.make_class(["cp_thumb"])
@@ -99,7 +111,9 @@ initialize_client(atoms) =
thumb_over = WStyler.make_class(["thumb_over"])
gauge = WStyler.make_class(["gauge"])
}
- change_size(set_size) = Session.send(treat_msg, {~set_size})
+ change_size(set_size) =
+ //do Log.info("change_size","{set_size}")
+ Session.send(treat_msg, {~set_size})
config_slider = { style=style_slider on_change=change_size on_release=change_size range=(1,50) init=5 step=2}
slider = WSlider.html(config_slider, "{id}_size")
@@ -112,12 +126,11 @@ initialize_client(atoms) =
| {some=img} -> do Canvas.draw_image(ctx, img, 0, 0)
Dom.hide(#initial_image)
| {none} -> Log.debug("draw image","empty")
- //apply patches if any
- do Session.send(treat_atoms, atoms)
//register session to reveive updates
- do NetworkBuffer.add(treat_atoms,atoms_network)
+ do Network.add(treat_lines,lines_network)
+ do register_to_server(treat_metric)
//Initial state
- do Session.send(treat_msg, {set_size=String.to_int(Dom.get_value(#slider))})
+ do Session.send(treat_msg, {set_size=slider_size})
do Session.send(treat_msg, {set_color=Color.darkblue})
//function call when drawing
@@ -139,39 +152,37 @@ initialize_client(atoms) =
| {none} -> Log.debug("canvas","error")
end
+
/*
* Main page
*/
-
+@server
main() =
-
- // Get the initial state
- (atoms,image) = get_state()
-
- //If there is an image, we load it with <img ..>
- cur_image =
- if image == ""
- then <div onready={_ -> initialize_client(atoms)} style="display:none;"/>
- else <img id="initial_image" width="{canvas_width}" height="{canvas_height}" onready={_ -> initialize_client(atoms)} src="{image}" />;
-
//chat creation
chat=
id = Random.string(8)
config = CChat.default_config(id)
initial_content = default_chat.requester({ range = (0, config.history_limit) })
initial_display = {CChat.default_display(id, Random.string(8)) with reverse=false}
- CChat.create(config, default_chat, id, initial_display, initial_content, ignore)
+ CChat.create(config, default_chat, id, initial_display, initial_content, (_,_ -> void ) )
//main content
<>
<div id="container">
<div id="header">
- <div id="logo" />
+ <div id="logo">
+ <p>This is a demo application of the open source Opa technology.
+ <br />
+ Head to <a href="http://opalang.org">http://opalang.org</a>
+ to learn how to program real-time, distributed, web applications.
+ </p>
+ </div>
</div>
<div id="content">
<div id="canvas_wrapper" width="{canvas_width}" height="{canvas_height}" >
<canvas id="canvas" width="{canvas_width}" height="{canvas_height}"></canvas>
- {cur_image}
+ <img id="initial_image" width="{canvas_width}" height="{canvas_height}"
+ onready={_ -> Scheduler.sleep(800,->initialize_client())} src="img.png" />
</div>
<div id="drawing_tools" />
</div>
@@ -185,6 +196,13 @@ main() =
<input type="button" onclick={sendit} value="send it"/>
<span id="sent"></span>
</div>
+ <div id="stats">
+ <p> users: <span id=#nb_user /></p>
+ <p> distance: <span id=#distance /></p>
+ </div>
+ <div class="source">
+ Get the sources and fork on
+ <a href="https://github.com/hhugo/OpaWhiteBoard">Github</a></div>
</div>
</>
@@ -220,16 +238,3 @@ sendit(_)=
| _ -> void
end
-
-@server @publish
-sendit_server(email,img)=
- img = String.drop_left(22,img) //in order to drop "data:image/png;base64,"
- content =
- "Here is your masterpiece\n\nThanks"
- Email.try_send_with_files_async(
- Email.of_string("canvas@opalang.org"),
- email,
- "Piece of art",
- {text=content},
- [{filename="masterpiece.png" content=img encoding="base64" mime_type="image/png"}],
- (_ -> void) )
View
131 src/v2/main.opa
@@ -0,0 +1,131 @@
+/* Collaborative white board
+
+ Copyright (C) 2010-2011 MLstate
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ @author Hugo Heuzard
+*/
+
+
+import stdlib.widgets.{slider,colorpicker}
+import hh.cairo
+/*
+ * Type of line (from, to, color, size)
+ */
+type line = (Dom.Dimension.t, Dom.Dimension.t, Color.color, int)
+
+/*
+ * Size of the board
+ */
+@both_implem
+canvas_width = 600.
+@both_implem
+canvas_height = 450.
+
+@server
+surface = Cairo.create_surface(Int.of_float(canvas_width),Int.of_float(canvas_height))
+context = Cairo.create(surface)
+
+/*
+ * Initialisation of chat component
+ */
+@server
+default_chat = CChat.init(CChat.default_config(Random.string(10)))
+
+/*
+ * Main
+ */
+resources = @static_include_directory("resources")
+
+urls = parser
+ | "/" ->
+ Resource.full_page(
+ "Play with Canvas", main(),
+ <link rel="stylesheet" href="style.css" type="text/css" />,{success}, [])
+ | "/img.png" -> Resource.dyn_image(Cairo.to_png(surface))
+ | "/style.css" -> Resource.source(@static_content("resources/style.css")(),"text/css")
+ | "/" r=Rule.of_map(resources) -> r
+
+
+server = Server.simple_server(urls)
+
+@server @publish
+lines_network : Network.network(list(line)) = Network.empty()
+
+do Scheduler.timer(300,->
+ Buffer.flush(server_flow,(l->
+ if not(List.is_empty(l))
+ then Network.broadcast(l,lines_network))
+ ))
+
+@server_private
+treat_msg(size,color,x1,y1,x2,y2) =
+ dx = (x1-x2)
+ dy = (y1-y2)
+ d = Math.sqrt_f(Float.of_int(dx*dx + dy*dy))
+ do Session.send(dist,{add=Int.of_float(d)})
+ fl=Float.of_int
+ size=Float.of_int(size)
+ do Cairo.set_stroke_line(context,color)
+ do Cairo.set_line_width(context,size)
+ do Cairo.draw(context,fl(x1),fl(y1),fl(x2),fl(y2))
+ void
+
+@server
+server_flow : Buffer.t(line) = Buffer.make()
+
+@server @publish @async
+drawing(actions) =
+ List.iter((from,to,co,size) as line ->
+ do Buffer.add(server_flow,line)
+ treat_msg(size,co,from.x_px,from.y_px,to.x_px,to.y_px),
+ actions)
+
+@server @publish
+register_to_server(info)=
+ _ = Session.on_remove(info, ->
+ do println("client disconnected")
+ Session.send(dist,{rem}))
+ _ = Session.send(dist,{new})
+ _ = Network.add(info, metric_network)
+ void
+
+ @server @publish
+sendit_server(email,img)=
+ img = String.drop_left(22,img) //in order to drop "data:image/png;base64,"
+ content =
+ "Here is your masterpiece\n\nThanks"
+ Email.try_send_with_files_async(
+ Email.of_string("canvas@opalang.org"),
+ email,
+ "Piece of art",
+ {text=content},
+ [{filename="masterpiece.png" content=img encoding="base64" mime_type="image/png"}],
+ (_ -> void) )
+
+@server @publish
+metric_network : Network.network((int,int)) = Network.empty()
+@server @publish
+dist = Session.make((0,0,false), ((nb,d,updt),msg ->
+ match msg with
+ | {new} ->
+ {set=(nb+1,d,true)}
+ | {dump} -> do if updt
+ then Network.broadcast((nb,d),metric_network)
+ {set=(nb,d,false)}
+ | {~add} -> {set=(nb,d+add,true)}
+ | {rem} -> {set=(nb-1,d,false)}))
+
+do Scheduler.timer(500,-> Session.send(dist,{dump}))

0 comments on commit dac365f

Please sign in to comment.