home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / ipl / gprocs / vdialog.icn < prev    next >
Text File  |  2000-07-29  |  9KB  |  297 lines

  1. ############################################################################
  2. #
  3. #    File:     vdialog.icn
  4. #
  5. #    Subject:  Procedures for dialog boxes
  6. #
  7. #    Author:   Jon Lipp
  8. #
  9. #    Date:     November 5, 1997
  10. #
  11. ############################################################################
  12. #
  13. #   This file is in the public domain.
  14. #
  15. ############################################################################
  16. #
  17. #  Vidgets defined in this file:
  18. #
  19. #    Vdialog
  20. #
  21. ############################################################################
  22. #
  23. #  Requires:  Version 9 graphics
  24. #
  25. ############################################################################
  26. #
  27. #  Links:  vbuttons, vtext
  28. #
  29. ############################################################################
  30.  
  31. link vbuttons
  32. link vtext
  33.  
  34. record DL_pos_rec(x,y)        # dialog position record
  35.  
  36. ############################################################################
  37. #  Vdialog - allows a pop-up menu_frame to be associated with a button.
  38. #
  39. #  Open the dialogue, let the user edit fields, one entry per field.
  40. #  returns a list containing the values of the fields.
  41. #
  42. ############################################################################
  43. record Vdialog_frame_rec(win, padx, pady, callback, aw, ah, lookup,
  44.    draw, id, ax, ay, uid, F, P,  V)
  45.  
  46. procedure Vdialog(params[])
  47.    local self
  48.    static procs
  49.  
  50.    initial {
  51.       procs := Vstd(event_Vframe, draw_Vframe, 1,
  52.                    resize_Vframe, inrange_Vpane, init_Vdialog,
  53.                    couplerset_Vpane, insert_Vdialog, remove_Vframe,
  54.                    lookup_Vframe, set_abs_Vframe)
  55.       if /V_OK then VInit()
  56.    }
  57.  
  58.    self := Vdialog_frame_rec ! params[1:5|0]
  59.    Vwin_check(self.win, "Vdialog()")
  60.    if (\self.padx, not numeric(self.padx) ) then
  61.       _Vbomb("invalid padx parameter to Vdialog()")
  62.    if (\self.pady, not numeric(self.pady) ) then
  63.       _Vbomb("invalid pady parameter to Vdialog()")
  64.  
  65.    self.uid := Vget_uid()
  66.    self.V := procs
  67.    self.F := Vstd_dialog(open_dialog_Vdialog, register_Vdialog,
  68.              format_Vdialog, unregister_Vdialog)
  69.    self.P := Vstd_pos()
  70.    self.V.init(self)
  71.    return self
  72. end
  73.  
  74. procedure open_dialog_Vdialog(self, x, y, values, def_str)
  75.    local i, c, e, newfocus, tid, rv, now, val
  76.    local entry, r, def, sel, v, args, parent, posn
  77.    static xytable, type
  78.  
  79.    initial {
  80.       xytable := table()
  81.       type := proc("type", 0)        # protect attractive name
  82.       }
  83.  
  84. ## Check ID and determine x and y values.
  85.    if \x then {
  86.       if WAttrib(self.win, "canvas") == ("normal" | "maximal") then  {
  87.      x +:= WAttrib(self.win, "posx")
  88.      y +:= WAttrib(self.win, "posy")
  89.      }
  90.       }
  91.    else if \y then {
  92.       /xytable[y] := DL_pos_rec()
  93.       posn := xytable[y]
  94.       x := posn.x
  95.       y := posn.y
  96.       }
  97.  
  98.    if WAttrib(self.win,"canvas") == ("normal" | "maximal") then  {
  99.       /x := WAttrib(self.win,"posx") + (WAttrib(self.win,"width")-self.aw) / 2
  100.       /y := WAttrib(self.win,"posy") + (WAttrib(self.win,"height")-self.ah) / 2
  101.       /x <:= 20
  102.       /y <:= 10
  103.       }
  104.  
  105. ## Sort text entry list.
  106.    self.F.text_entries := sort(self.F.text_entries)
  107.    every i := 1 to *self.F.text_entries do
  108.       self.F.text_lu[self.F.text_entries[i]] := i
  109.  
  110. ## Build arg list and open window
  111.    args := []
  112.    put(args, "size=" || self.aw || "," || self.ah)
  113.    put(args, "pos=" || \x || "," || \y)
  114.    put(args, "display=" || WAttrib(self.win, "display"))
  115.    put(args, "label=" || ("" ~== WAttrib(self.win, "label")))
  116.    put(args, "font=" || WAttrib(self.win, "font"))
  117.    put(args, "gamma=" || WAttrib(self.win, "gamma"))
  118.    if (c := Fg(self.win))[1] ~== "-" then
  119.       put(args, "fg=" || c)
  120.    if (c := Bg(self.win))[1] ~== "-" then
  121.       put(args, "bg=" || c)
  122.    parent := self.win
  123.    if not (self.win := WOpen ! args) then {
  124.       write(&errout, "can't open window for dialog")
  125.       writes(&errout, "window arguments:")
  126.       every writes(&errout, " ", !args | "\n")
  127.       stop()
  128.       }
  129.  
  130.    every v := !self.draw do {
  131.       v.win := self.win
  132.       if type(v) == ("Vradio_frame_rec" | "Vscrollbar_frame_rec") then
  133.          every (!v.draw).win := self.win
  134.       }
  135.    self.V.resize(self, 0, 0, self.aw, self.ah)
  136.  
  137. ## Make a sorted list of self.F.entries
  138.    sel := sort(self.F.entries, 1)
  139. ## set values of fields to value list, or default if entry is &null
  140.    every i := 1 to *sel do {
  141.       entry := sel[i][2]
  142.       val := values[i] | &null
  143.       (\entry).V.set_value(entry, val)
  144.       }
  145.    self.F.focus := &null
  146.    self.V.draw(self)
  147.  
  148. ## Find default button according to def_str.
  149.    if \def_str then
  150.       every i := !self.lookup do
  151.          if def_str == \i["s"] then {
  152.             def := i
  153.             break
  154.             }
  155.  
  156.    self.F.focus := self.F.entries[self.F.text_entries[1]]
  157.    newfocus := \self.F.focus | \sel[1][2] | &null
  158.    (\self.F.focus).T.block(self.F.focus)
  159.  
  160. ## Call the user initialization callback, if any.
  161.    (\self.callback)(self)
  162.  
  163.    repeat {
  164.       # outline the default button every time around, in case the outline was
  165.       # erased by a redraw call for the dialog (e.g. in ColorDialog())
  166.       BevelRectangle((\def).win, def.ax-5, def.ay-5, def.aw+10, def.ah+10,-2)
  167.  
  168.       e := Event(self.win)
  169.       if e === "\r" then {
  170.          if \def then {
  171.             e := &lpress
  172.             &x := def.ax + 1
  173.             &y := def.ay + 1
  174.             Enqueue(def.win, &lrelease, def.ax + 1, def.ay + 1)
  175.          }
  176.          else next
  177.       }
  178.       if integer(e) < 0 then {
  179.          newfocus := self.V.lookup(self, &x, &y) | self.F.focus
  180.          if ((\newfocus).id) ~=== ((\self.F.focus).id) then
  181.             switch_focus_Vdialog(self, newfocus)
  182.       }
  183.       r := (\newfocus).V.event(newfocus, e, &x, &y) | &null
  184.       case r of {
  185.          V_NEXT: {     #move to next entry
  186.             now := self.F.text_lu[self.F.focus.id]
  187.             tid := ((*self.F.text_entries >= now + 1) | 1)
  188.             switch_focus_Vdialog(self, self.F.entries[self.F.text_entries[tid]])
  189.             }
  190.          V_PREVIOUS: {    #move to previous entry
  191.             now := self.F.text_lu[self.F.focus.id]
  192.             tid := ((1 <= now - 1) | *self.F.text_entries)
  193.             switch_focus_Vdialog(self, self.F.entries[self.F.text_entries[tid]])
  194.             }
  195.          V_OK: {    # done, quit with changes
  196.             rv := []
  197.             every e := !sel do put(rv, e[2].data)
  198.             break
  199.             }
  200.          V_CANCEL: {     # cancel changes, quit.
  201.             break
  202.             }
  203.       }
  204.       newfocus := self.F.focus
  205.    } # end repeat
  206.  
  207. ## close temporary window after saving its location for next time
  208.    (\posn).x := WAttrib(self.win, "posx")
  209.    (\posn).y := WAttrib(self.win, "posy")
  210.    WClose(self.win)
  211.  
  212. ## restore window fields
  213.    self.win := parent
  214.    every v := !self.draw do {
  215.       v.win := self.win
  216.       if type(v) == ("Vradio_frame_rec" | "Vscrollbar_frame_rec") then
  217.          every (!v.draw).win := self.win
  218.       }
  219.  
  220. ## flush pending events that may have accumulated on the parent window
  221.    while *Pending(self.win) > 0 do
  222.       Event(self.win)
  223.  
  224. ##  For Vtext vidgies, tell them to turn off their cursors.
  225.    every tid := !self.F.text_entries do
  226.       \(self.F.entries[tid]).T.CursorOn := &null
  227.  
  228.    return \rv
  229. end
  230.  
  231. procedure switch_focus_Vdialog(self, newfocus)
  232.    if (newfocus.id === !self.F.text_entries) then {
  233.       self.F.focus.T.unblock(self.F.focus)
  234. #      self.F.focus.T.erase_cursor(self.F.focus)
  235.       newfocus.T.block(newfocus)
  236.       self.F.focus := newfocus
  237.       }
  238. end
  239.  
  240. procedure insert_Vdialog(self, vidget, x, y)
  241.    if /self | /vidget | /x | /y then
  242.       _Vbomb("incomplete or &null parameters to VInsert() for dialogs")
  243.    pad_and_send_Vdialog(self, vidget, x, y)
  244. end
  245.  
  246. procedure register_Vdialog(self, vidget, x, y)
  247.    static type
  248.  
  249.    initial type := proc("type", 0)    # protect attractive name
  250.  
  251.    if /self | /vidget | /x | /y then
  252.       _Vbomb("incomplete or &null parameters to VRegister()")
  253.    self.F.entries[vidget.id] := vidget
  254.    if type(vidget) ? find("text") then
  255.       put(self.F.text_entries, vidget.id)
  256.    pad_and_send_Vdialog(self, vidget, x, y)
  257. end
  258.  
  259. procedure unregister_Vdialog(self, kid)
  260. local new, i
  261.  
  262.    if (kid.id === !self.F.text_entries) then {
  263.       new := []
  264.       every i := !self.F.text_entries do if kid.id ~=== i then put(new, i)
  265.       self.F.text_entries := new
  266.       }
  267.    delete(self.F.entries, kid.id)
  268.    every i := 1 to *self.F.text_entries do
  269.       self.F.text_lu[self.F.text_entries[i]] := i
  270.    self.V.remove(self, kid, 1)
  271. end
  272.  
  273. procedure pad_and_send_Vdialog(self, vidget, x, y)
  274.    static type
  275.  
  276.    initial type := proc("type", 0)    # protect attractive name
  277.  
  278.    if (x|y) < 0 | type(x|y) == "real" then
  279.       _Vbomb("must VRegister() or VInsert() a vidget to a dialog with absolute coordinates")
  280.    insert_Vframe(self, vidget, x+self.padx, y+self.pady)
  281. end
  282.  
  283. procedure format_Vdialog(self)
  284.    self.V.resize(self, 0, 0,
  285.                  Vmin_frame_width(self)+self.padx-1,
  286.                  Vmin_frame_height(self)+self.pady-1)
  287. end
  288.  
  289. procedure init_Vdialog(self)
  290.    init_Vframe(self)
  291.    /self.padx := 20
  292.    /self.pady := 20
  293.    self.F.entries := table()
  294.    self.F.text_entries := []
  295.    self.F.text_lu := table()
  296. end
  297.