#
# $Id: list.icn,v 1.4 2004/11/06 00:28:13 rparlett Exp $
#
# This file is in the public domain.
#
# Author: Robert Parlett (parlett@dial.pipex.com)
#

package gui
link graphics


$include "guih.icn"

class ListLabel:Label()
   method handle_event(e)
      if \self.has_focus then {
         if e === Key_Up then
            parent.go_up(e)
         else if e === Key_Down then 
            parent.go_down(e)
      }
   end
end

#
#
# This component is for selecting one string from a list of
# several.  When a button is pressed a list appears (possibly
# with a scroll bar) from which one item can be selected.
# 
# A SELECTION_CHANGED_EVENT is generated whenever an item is selected from the
# list.
# 
# @example
# @ l := List()
# @ l.set_selection_list(["Red", "Green", "Yellow", "Blue", "Orange"])
# @ l.set_size(120)
# @ l.set_pos(100, 100)
# @ l.set_selection(2)  # Green will be the first selection
# @ self.add(l)
#
class List : DropDown(
   l,                       #         
   constant_label           #
   )

   method apply_selection()
     self.l.set_label(\self.constant_label | self.selection_list[self.selection])
     self.invalidate()
   end

   #
   # The given string will always appear in the text part of the
   # component, rather than the currently selected item.
   #
   method set_constant_label(x)
      return self.constant_label := x
   end

   method firstly()
      self.DropDown.firstly()
      self.l.set_label(\self.constant_label | self.selection_list[self.selection])
   end

   method resize()
      local bw

      if /self.selection_list then
         fatal("no selection list specified")

      #
      # Re-sized with text list showing, just get rid of it
      #
      if \self.tl then {
         self.close_textlist()
         self.unique_end()  
      }

      /self.h_spec := WAttrib(self.cwin, "fheight") + 2 * DEFAULT_TEXT_Y_SURROUND
      self.Component.compute_absolutes()

      bw := self.h - 2 * BORDER_WIDTH

      #
      # Set button position and size
      #
      b.set_pos(self.w - BORDER_WIDTH - bw, BORDER_WIDTH)
      b.set_size(bw, bw)
      b.resize()

      #
      # Set label position and size - reflect the way the textlist works.
      #
      l.set_pos(DEFAULT_TEXT_X_SURROUND - HIGHLIGHT_TEXT_SPACING,
                BORDER_WIDTH)
      l.set_size(self.w - bw - 2 * (DEFAULT_TEXT_X_SURROUND - HIGHLIGHT_TEXT_SPACING),
                 self.h - 2 * BORDER_WIDTH)

      l.resize()

      return
   end

   method display(buffer_flag)
      #
      # Draw text element 
      #
      EraseRectangle(self.cbwin, self.x, self.y, self.w, self.h)
      DrawSunkenRectangle(self.cbwin, self.x, self.y, self.w, self.h)
      #
      # Draw button and list
      #
      self.b.display(1)
      self.l.display(1)
      self.do_shading(self.cbwin)
      if /buffer_flag then
         CopyArea(self.cbwin, self.cwin, self.x, self.y, self.w, self.h, self.x, self.y)
   end

   method set_one(attr, val)
      case attr of {
         "selection" : set_selection(int_val(attr, val))
         "constant_label" : set_constant_label(string_val(attr, val))
         default: self.DropDown.set_one(attr, val)
      }
   end

   #
   # Manage our own focus/accelerator handling so that the label always gets the focus.
   #
   method find_focus()
      if self.is_unshaded() & self.in_region() & self.is_unhidden() then
         return l
   end

   method find_accel(e)
      if self.Component.find_accel(e) then
         return l
   end

   initially(a[])
      self.DropDown.initially()
      self.l := ListLabel()
      self.l.set_label("")
      self.l.set_accepts_focus()
      self.add(l)
      set_fields(a)
end