The Anubis/Paradize Project. The simple window widget. Copyright (c) Alain Prouté 2004-2005. Authors: Alain Prouté Olivier Duvernois read tools/basis.anubis read widget.anubis This file defines simple 'nude' windows. If you need more sophisticated windows (with boundary and/or scrollbars) see 'widgets3/window.anubis'. A 'simple window' is a rectangular area which is able to show part of another widget (its 'content') through itself: +...........................+ : content : : : : : : : : +-------------+ : : | window | : : | | : : | | : : | | : : | | : : | | : : +-------------+ : : : : : +...........................+ The window has a position relative to its content. This position should not be confused with the position of the window relative to its parent widget or relative to the host window. Also a window may change its size. The size of a window must eventually be coordinated with the size of another window. It may be changed from outside the window, the position of the content may also be changed or read from outside the window, for example by scrollbars. For these reasons, these dimensions are stored in variables which must be provided at the creation. A simple window widget is created by: public define Widget create_simple_window ( Var(Int32) win_w, // width of window Var(Int32) win_h, // height of window Var(Int32) window_x_scroll, // position of window relative to its content Var(Int32) window_y_scroll, Widget content, ). --- That's all for the public part ! -------------------------------------------------- If (cont_w,cont_h) is the size of the content, and (win_w,win_h) the size of the window, we must always have: 0 =< window_x_scroll =< sup(0,cont_w - win_w) 0 =< window_y_scroll =< sup(0,cont_h - win_h) In other words, 'window_x_scroll' is 0 when the window is wider than its content. The window widget handles events as follows. - keyboard event: do nothing, - mouse move event: - if mouse captured: change values of 'window_x_scroll' and 'window_y_scroll' - otherwise: transmit to content, - mouse click event: - left down: if content does not handle, capture the mouse - left up: if mouse captured, uncapture the mouse, otherwise transmit to content - other: transmit to content *** Managing window event The function 'do_when_moved' is called at each mouse event when the mouse is captured by the window. define WidgetAnswer do_when_moved ( KeyboardState ks, WidgetMouseCapturedEvent e, Widget content, Var(Int32) win_w, Var(Int32) win_h, Var(Int32) window_x_scroll, Var(Int32) window_y_scroll, Var((Int32,Int32)) move_ref ) = if get_size(content)(unique) is (cont_w,cont_h) then with xe = x(e), ye = y(e), if *move_ref is (mrx,mry) then window_x_scroll <- max(0,min(*window_x_scroll -xe+mrx,cont_w-*win_w)); window_y_scroll <- max(0,min(*window_y_scroll -ye+mry,cont_h-*win_h)); move_ref <- (xe,ye); handled([rect(0,0,*win_w,*win_h)]). if e is { moved(x,y) then if *move_ref is (mrx,mry) then window_x_scroll <- max(0,min(*window_x_scroll -x+mrx,cont_w-win_w)); window_y_scroll <- max(0,min(*window_y_scroll -y+mry,cont_h-win_h)); move_ref <- (x,y); forget((WidgetPositionToolBox ptb) |-> set_position(content)(ptb,position(*window_x_scroll,*window_y_scroll))); handled([rect(0,0,*win_w,*win_h)]), liberated(x,y) then if *move_ref is (mrx,mry) then window_x_scroll <- max(0,min(*window_x_scroll -x+mrx,cont_w-win_w)); window_y_scroll <- max(0,min(*window_y_scroll -y+mry,cont_h-win_h)); move_ref <- (x,y); forget((WidgetPositionToolBox ptb) |-> set_position(content)(ptb,position(*window_x_scroll,*window_y_scroll))); handled([rect(0,0,*win_w,*win_h)]), }. define WidgetAnswer manage_window_event ( WidgetEventToolBox etb, WidgetNormalEvent e, Widget content, Var(Int32) win_w, Var(Int32) win_h, Var(Int32) window_x_scroll, Var(Int32) window_y_scroll, Var((Int32,Int32)) move_ref ) = if e is { mouse_gone then not_handled([]), mouse_move(ks, x, y) then not_handled([]), mouse_click(ks, mc, x, y) then if mc is { left_down then (move_ref <- (x,y)); forget( capture_mouse (etb, (KeyboardState ks1, WidgetMouseCapturedEvent e1) |-> do_when_moved(ks1,e1,content, win_w,win_h, window_x_scroll,window_y_scroll, move_ref))); resized, left_up then not_handled([]), middle_down then not_handled([]), middle_up then not_handled([]), right_down then not_handled([]), right_up then not_handled([]), } }. *** Create Window public define Widget create_simple_window ( Var(Int32) win_w, // width of window Var(Int32) win_h, // height of window Var(Int32) window_x_scroll, // position window relative to its content Var(Int32) window_y_scroll, Widget content, ) = with move_ref = var(((Int32,Int32)) (0,0)), monitor = (WidgetMonitoringToolBox mtb, List(WidgetRectangle) -> One redraw) |-> redraw([rect(0,0,*win_w,*win_h)]), create_widget ( /* Set positions of childs */ (WidgetPositionToolBox ptb) |-> set_position(content)(ptb,position(-(*window_x_scroll),-(*window_y_scroll))), /* Get size */ (One u) |-> (*win_w, *win_h), /* Redraw the window */ (WidgetDrawToolBox dtb) |-> redraw(content)(dtb,rect(0,0,*win_w,*win_h)), /* Duplicate */ (One u) |-> create_simple_window(win_w,win_h,window_x_scroll,window_y_scroll, duplicate(content)(unique)), /* Change size */ (Int32 w, Int32 h) |-> win_w <- max(10,w); win_h <- max(10,h), /* Handle normal events */ (WidgetEventToolBox etb, WidgetNormalEvent e) |-> if main_event_handler(content)(etb,e) is { not_handled(l) then join(not_handled(l), manage_window_event (etb, e, content, win_w,win_h, window_x_scroll,window_y_scroll, move_ref)), handled(lwr) then handled(lwr), resized then handled([rect(0,0,*win_w,*win_h)]) }, /* Register variables to monitor */ (List(WidgetRegistration)) [ register(win_w,monitor), register(win_h,monitor), register(window_x_scroll,monitor), register(window_y_scroll,monitor), ] ).