While the Cyphre 's code is not released, I publish here the result of an
old effort to have a cascaded menu style.
There's still some bugs, specially sometimes when a cascaded menu pane is
displayed and a clik is made on a menu header.

I appreciate any help to finish the job, because I cant' find the problem..

Philippe Oehler

   REBOL [
 title: "View Menu"
 authors: "Frank Sievertsen (version 1.0.0) & Philippe Oehler (v.2.0.0)"
 date:22-5-04/14:39
 version: 2.0.0
 purpose: "Adds a grafical menu to a window or a face + Cascaded-menu"
]


;/*****************************************/ Needed to run the script well,
with new version of View
flag-face?: func [
    "Checks a flag in a VID face."
    face [object!] 'flag
][all [in face 'flags face/flags find face/flags flag]]
;/*****************************************/

ao2: :print ; a function, that I actually activates/deactivates, to be
simple, here : ao2: : print


;/*****************************************/head of the object!
CONTEXT [
 ;/*****************************************/
 ; LOCAL PARSE - VARS
 t1: t2: none
 name: none
 out-block: none
 out-face: none
 SUB-out-face: none
 ;SUB-out-block: COPY []
 offset: 0x0
 direction: 0x1
 menu: none
 degree-from-top-face: ""

 ;/*****************************************/

 ;[STYLIZE];/*****************************************/;
 MENU-I-STYLES: stylize [

  ;[STYLE : MENU-ITEM];/*****************************************/;
  menu-item:
   txt bold font-name "verdana" black "" font-size 10 with [
   pane-size: 900x900
   colors: reduce [[gradient 1x1 167.163.179 167.163.179] none];colors:
reduce [167.163.179 none]
   Append init [state: no]
   state: no
   menu-description: none      ;its text'  block
   menu-action: none        ;its behavior
   title-of-submenu?: none
   menu-number: 0
   parent-name: ""
   path-from-system-for-Cascaded-Menu: "" ; to be a private data, shared
into different funcs
   init: [
    size: 900x900
    size: (size-text self) + para/origin + para/margin
   ]
   para: make para [ margin: origin: 4x2 ]
  ]

  feel [
   redraw: func [face][
    face/color: pick face/colors face/state
   ]
   over: func [face action event][
    face/state: action
    show face
   ]
   engage: func [face action event][
    switch action [
     down [         ;ao2 "normal action of the basic style"
      ;ao2 "CALL unview-menu"
      unview-menu     ;effacement du menu déroulé
      face/menu-action face    ;call the menu' menu-action with its argument
face
      IF face/menu-description [   ;if there's something in the block's
menu-descritption.
       unview-menu    ;time 1 : unview of the menu displayed
       view-menu face    ;time 2 : 'redraw'
      ]
     ]
     away [
      over face no event    ;calling of the function 'over with  false (no)
as 2nd argument
     ]
     over [
      over face yes event    ;calling of the function 'over with true (yes)
as 2nd argument
  ] ] ] ]
  ;/*****************************************/ end of MENU-ITEM

 ] ;/*****************************************/;
 ;[/STYLIZE]


 ;/*****************************************/; Menu-Functions
 Unview-menu: func [][
  ao2 "ENTR UNVIEW-MENU"
  IF menu [
   ;ao2 "Menu activated!"
   remove find menu/parent-face/pane menu
   show menu/parent-face
   menu: none
  ]
  IF error? try [
   IF Cascaded-menu [
    ;ao2 "mark 161"
    unview-Cascaded-menu
    Cascaded-menu: none
   ]
  ][]
 ]

 ;/*****************************************/
 Unview-Cascaded-menu: func [/only][
  ;ao2 "ENTR Unview-Cascaded-menu"
  nb-Cascaded-menu: 0
  IF Cascaded-menu [
   ;AO2 "Cascaded-menu activated!!!"
   remove find Path-from-system-for-Cascaded-Menu Cascaded-menu
   show Path-from-system-for-Cascaded-Menu
   Cascaded-menu: none
  ]
  IF Not only [
   IF menu [
    ;ao2 "CALL unview-Cascaded-menu"
    unview-menu
    menu: none
  ] ]
  ;ao2 "DONE Unview-Cascaded-menu"
 ]

 ;/*****************************************/
 view-Cascaded-menu: func [
  bk
  /minimize
 ][
  ao2 "ENTR view-Cascaded-menu"
  len-bk: length? bk
  offs: sub-offset    ;private variable of the object!
  either global-affichage-old-school
  [ path-from-system-for-Cascaded-Menu:
system/view/screen-face/pane/1/pane/8/pane/pane ]
  [ path-from-system-for-Cascaded-Menu:
ystem/view/screen-face/pane/1/pane  ]
  Append path-from-system-for-Cascaded-Menu Cascaded-menu: make
system/words/face [
   dirty?: yes
   flags: [on-unfocus]
  ]

  Cascaded-menu/edge: make Cascaded-menu/edge [ effect: 'bevel  color:
200.200.200  size: 2x1 ]
  Cascaded-menu/color: 212.212.212
  ;Cascaded-menu/effect: [  merge gradmul 1x1 212.212.212 212.212.212];
120.255.195
  Cascaded-menu/pane: copy []


  EITHER Not minimize [
   size-x: 0
   forEach item bk [      ;calcul de la longueur maximale du sous-menu
    size-text-x: (my-size-text item/text) + 8x0
    size-x: max size-x (size-text-x/x)
   ]
  ][ size-x: 0 ]

  o: 0x0

  forEach item bk [
   item/colors: reduce [[gradient 1x1 167.163.179 167.163.179] none]

   item/offset/y:  o/y
   item/size: To-pair (join size-x "x18")
   item/feel/redraw:  func [face][
    face/effect: pick face/colors face/state
   ]
   item/feel/over: func [face action event][
    EITHER all [(face/parent-name = "")(Not face/title-of-submenu?) ]  [
     unview-Cascaded-menu/only isCascaded-menu-visible?: false
     unfocus
     system/view/focal-face: menu
    ][
     view-Cascaded-menu-procedure
    ]
    face/state: action ; true or false
    show face
   ]
   Append Cascaded-menu/pane item
   o/y: o/y + 18
  ]

  Cascaded-menu/offset: offs
  Cascaded-menu/size/y: 18 * len-bk
  Cascaded-menu/size/x: size-x

                  ;alert faceOne/parent-face/text
  show path-from-system-for-Cascaded-Menu ; Those line is important !! the
path depends on where is the menu related the system path
  unfocus
  ;system/view/focal-face: Cascaded-menu ; I remove this line, producing the
right action of items that are Not in a Cascaded-menu

  ;/*****************************************/;
  Cascaded-menu/action: func [face value][
   unview-Cascaded-menu
  ]
  ;/*****************************************/;
  ao2 "DONE view-Cascaded-menu"
 ]

 ; not necessary, those function doesn't the right job. If someone can make
this function right.
 ;/*****************************************/;
 Set-degree-from-top-face: func [face /local i][
  the-path: face/parent-face
  ;print mold "lll"
  ;print mold face/var
  i: 1
  if not none? the-path [
   i: 2
   the-path: face/parent-face/parent-face
   if not none? the-path [
    i: 3
    the-path: face/parent-face/parent-face/parent-face
    if not none? the-path [
     i: 4
     the-path: face/parent-face/parent-face/parent-face/parent-face
     if not none? the-path [
      i: 5
      the-path: face/parent-face/parent-face/parent-face/parent-face
      if not none? the-path [
       i: 6
       the-path: face/parent-face/parent-face/parent-face/parent-face
      ]
     ]
    ]
   ]
  ]
  return i
 ]



 isCascaded-menu-visible?: false
 ;/*****************************************/;
 view-Cascaded-menu-procedure: does  [
  IF Not isCascaded-menu-visible? [view-Cascaded-menu Cascaded-menu-block
isCascaded-menu-visible?: true]
 ]


 Cascaded-menu-block: copy []
 sub-offset: 0x0
 ;/*****************************************/;
 View-menu: func [face /local tmp][
  ao2 "ENTR view-menu"
  ;the object 'menu is added to the system' words
  ;ao2 mold face/parent-face/parent-face/pane
  Set-degree-from-top-face face; call of this function, but it doesn't work
yet

  ; The next 2 lines are specific to the place where the menu is placed
related to the system root
  MyPath-pane:  face/parent-face/parent-face/pane
  ;MyPath-pane:  face/parent-face/pane
  MyPath: face/parent-face/parent-face
  ;MyPath: face/parent-face

  clear Cascaded-menu-block

  Append face/parent-face/parent-face/pane menu: make system/words/face [
;append the menu to the main pane (layout) where is the menu
   dirty?: yes
   flags: [on-unfocus]
  ]

  menu/edge: make menu/edge [ effect: 'bevel color: 200.200.200 size: 2x1]
  menu/offset: face/offset + 0x18 + face/parent-face/offset
  menu/color: none
  menu/effect: [
   gradient 1x1 212.212.212 212.212.212
    ;;;;;6-merge gradmul 0x8 97.99.135 97.99.135; 120.255.195
   ;merge gradmul 0x1 115.115.195 120.120.195
   ;multiply 85.85.85
   ;merge gradcol 0x1 250.250.250 250.250.250
  ]

  build-menu/below menu face/menu-description ; actually the parsing of the
dialect is called

  menu/size: 1x1
  menu/size/x: face/size/x
  has-OneCascade-InPane?: false
  offs: 1x1

  IF menu/pane/1 [une-hauteur: menu/pane/1/size/y]
  menu-pane-temp: copy menu/pane ; variable temp is used to remove find
menu/pane item because it's hard to make it in the foreach loop


  forEach item menu-pane-temp [
   SUB?: false
   IF error? try [
    IF item/user-data <> none [SUB?: has-OneCascade-InPane?: true]
   ][]

   EITHER SUB? = FALSE [ ;normal case
    menu/size: max menu/size item/offset + item/size
    item/size/x: menu/size/x
    offs/x: menu/offset/x + item/size/x + 2
    IF face/title-of-submenu? [
     ;ao2 ["title-of-submenu?" face/text ]
    ]
   ][
    Append/only Cascaded-menu-block item  ;ao2 menu/offset/x
    offs/y: menu/offset/y + item/size/y  ; ao2 ["--->" length? menu/pane]
    remove find menu/pane item   ; ao2 ["--->" length? menu/pane]
  ] ]

             ;IF face/title-of-submenu? [ao2 face/text ]
  menu/size: menu/size + 2x2
  show myPath
  unfocus
  system/view/focal-face: menu

  menu/action: func [face value][  unview-menu ao2 "2-unview" ]

  print has-OneCascade-InPane?

  IF has-OneCascade-InPane? [
   offs/y: offs/y - une-hauteur
   sub-offset: offs
   ;;;;6-view-Cascaded-menu/minimize Cascaded-menu-block ; args 1 : la face
(le sous-sous-menu) ; arg 2 : l'offset
   view-Cascaded-menu Cascaded-menu-block ; args 1 : la face (le
sous-sous-menu) ; arg 2 : l'offset
  ]
 ]


 ;/*****************************************/;
 Build-menu: func [face [object!] descr [block!] /below "without 'below, the
menu's elements are horizontal"][
  face/pane: out-block: copy []
  direction: EITHER below [0x1][1x0]
  IF Not parse Compose descr [menu-data][
   ;make error! "menu-parse error"
  ]
 ]
 ;/*****************************************/;



 ;===============
 ; PARSE - RULES
 menu-data: [
  (offset: 0x0)
  any menu-item
 ]

 menu-counter: 0
 ; Second rule of parsing
 menu-item: [
  set name string!        ;used for titles of menu + its elements but not
for cascaded menu's elements

  (out-face: make menu-i-styles/menu-item []) ;out-face become a style
element, then some specifities will be append
  (out-face/text: copy name)     ;out-face/text will be titles of the menu
  (out-face/offset: offset)      ; its offset

  any menu-options        ; second block of parsing rules (cf. below)
  (do out-face/init)        ;call of the init function of the style
  (offset: out-face/size * direction + offset)  ; the offset is *saved* to
later use
  (Append out-block out-face)     ; all infos (style + new infos) are added
to a larger block
  |            ; or, reading of the splitting and graphic creation of the
splitting line
  '--- (
   Append out-block t1: make face [
    size: 10x3 edge: make edge [
     effect: 'ibevel
     size: 1x1
     color: none
     color: 200.200.200
   ] ]
   t1/offset: offset
   offset: t1/size * direction + offset
  )
 ]


 reference-menu-name: ""
 ; begin with the name, then either it's a SUB, or a block
 menu-options: [
  'SUB set t1 block! (
   menu-counter: menu-counter + 1
   out-face/menu-description: t1
   out-face/font/color: 72.132.167
   out-face/menu-number: menu-counter
   ;ao2 out-face/menu-number
  )
  | set t1 block! (
   out-face/menu-action: func [face] t1
  )
  |
  'SUB-SUB set t2 block!
   (GLOBAL-existence-de-Cascaded-menu?: true)
   (out-face/title-of-submenu?: true)    ;it works
   (reference-menu-name: out-face/text)

   ;(out-face/menu-number: menu-counter)
    ;;;;;6-(ao2 out-face/menu-number)
   (parse t2 menu-SUB-options)     ;when it encounters SUB-SUB then block
parsing du block that follows
 ]
 ; what is after the  | is something that I added (Philippe)




 ; Rules for sub-options
 menu-SUB-options: [
  any [
   set SUB-name string!  ; the Name of SubMenu is set

   (SUB-out-face: make menu-i-styles/menu-item [])   ; sub-out-face become a
menu-item and has its style now
   (SUB-out-face/text: copy SUB-name) ; get-copy of the sub-name
   (sub-out-face/parent-name: reference-menu-name)

   (SUB-out-face/effect: menu/effect) ; get the main effect


   set t2 block! ; le block
   (
    SUB-out-face/menu-description: t2
    SUB-out-face/menu-action: func [face] t2
    SUB-out-face/user-data: true ; if <> none then the face will be a
Cascaded-menu
   )
   (do SUB-out-face/init)
   (Append out-block SUB-out-face);out-block is actually a face/pane! (a
kind of pointeur)
  ]

 ]





  ;/*****************************************/;

  system/words/menu-styles: stylize [
   menu: box 1x1 with [
    Append init: init [
     size: 1x1
     build-menu self second :action
    ]
    words: [
     SUB [
      ;ao2 "SUB"
     ]
     SUB-SUB []
    ]
   ] feel [
    engage: none
    redraw: func [face][
     face/offset: -1x-1
     face/size: face/parent-face/size + 10x1
     face/size/y: 19 ; starting menu height
    ]
   ]
   edge [effect: 'bevel size: 1x1 color: 200.200.200]


  ]

]
;[END OF CONTEXT]



; EXAMPLE :
;win: compose [ backdrop 212.212.212 origin 0x4 styles menu-styles]
myMenu: Compose/deep [
  menu [
   "File |" sub [
     "Save As" [save-as]
    ---
   ]
   "Edit |" sub [
    "Delete  -->" sub-sub [
     "Word" [delete-word]
     ("Line" [delete-line]
    ]
    ---
    "Cut" []
    "Copy" []
    "Paste" []
    ---
   ]
  ]
]
Append win Compose [Menu2: (myMenu)]



-- 
To unsubscribe from this list, just send an email to
[EMAIL PROTECTED] with unsubscribe as the subject.

Reply via email to