This Question is Possibly Answered

1 "correct" answer available (5 pts) 15 "helpful" answers available (3 pts)
3 Replies Last post: Oct 4, 2008 9:00 AM by Kamal

Want to use AutoComplete TextField with multiple values.

Oct 3, 2008 4:12 AM

Click to view mannusanghi's profile Level 2 mannusanghi 28 posts since
Feb 27, 2008
Hi...

I want to use AutoComplete TextField with multiple values.

Here is one example which is provided by curl but this uses only one selection at a time.

Source code of example is:


{curl 6.0 applet}
{curl-file-attributes character-encoding = "gb2312"}
 
{define-class package GuidePromptHelper
 
  field constant control:any
 
  field package-get prompt-value:#String
  field package-get input-color:FillPattern 
  field package-get input-background:Background
  field package-get prompt-color:FillPattern
  field package-get prompt-background:Background
 
  {constructor package {default
                           guide-prompt-control:any,
                           prompt-color:FillPattern,
                           prompt-background:Background
                       }
 
    set self.control = guide-prompt-control
    set self.prompt-color = prompt-color
    set self.prompt-background = prompt-background
 
    {with-compiler-directives
        allow-any-calls? = true, allow-implicit-any-casts? = true 
     do
        set self.prompt-value = self.control.prompt
        set self.input-color = self.control.color
        set self.input-background = self.control.control-content-background
        set self.control.color = self.prompt-color
        set self.control.control-content-background = self.prompt-background
    }
  }
 
  {method package {do-focus-in}:void
 
    {with-compiler-directives allow-any-calls? = true do
        set self.control.prompt = null
        set self.control.color = self.input-color
        set self.control.control-content-background = self.input-background
    }
  }
 
  {method package {do-focus-out}:void
 
    {with-compiler-directives allow-any-calls? = true do
        set self.control.prompt = self.prompt-value
        {if self.control.value == "" then
            {self.control.unset-value}
            set self.control.color = self.prompt-color
            set self.control.control-content-background = self.prompt-background
        }
    }
  }
}
{define-class public open CoreTextField
  {inherits TextField}
 
  field constant private prompt-helper:GuidePromptHelper
 
  {constructor public {default
                          prompt:#String = null,
                          prompt-color:FillPattern = "grey",
                          prompt-background:Background = "white",
                          ...
                      }
 
    {construct-super prompt = prompt, {splice ...}}
 
    || guide prompt
    set self.prompt-helper = 
        {GuidePromptHelper self, prompt-color, prompt-background}
  }
 
  || override
  {method public open {on-focus-in e:FocusIn}:void
 
    || guide prompt 
    {self.prompt-helper.do-focus-in}
  }
 
  {method public open {on-focus-out e:FocusOut}:void
 
    || guide prompt
    {self.prompt-helper.do-focus-out}
  }
}
 
{define-class public AutoCompleteTextField {inherits CoreTextField}
  
  let private active-tf:#AutoCompleteTextField
  let private init?    :bool = false
  
  field public menu-pane:#MenuPane
  
  field private _menu-height:any = null
  
  field private _proposed-values:#{Array-of String}
  
  || added by Akira Mori
  field public-get ignore-case?:bool
 
  {constructor public {default
                          data-model:#StringDataModel = null,
                          value:#String = null,
                          prompt:#String = null,
                          max-chars:int = -1,
                          proposed-values:#{Array-of String} = null,
                          menu-height:any = null,
                          ignore-case?:bool = true,
                          ...
                      }
    {construct-super
        {splice ...}
    }
    set self._proposed-values = proposed-values
    set self.menu-height = menu-height
    || added by Akira Mori
    set self.ignore-case? = ignore-case?
    
    {self.add-event-handler
        {on ValueChanged do
            {self.show-menu}
        }
    }
    
    {self.add-event-handler
        {on FocusOut do
            {self.hide-menu}
        }
    }
    
    {AutoCompleteTextField.init-auto-complete-text-field}
  }
  
  {define-proc private {init-auto-complete-text-field}:void
    {if AutoCompleteTextField.init?
     then
        {return}
    }
    
    let constant gui-manager:GuiManager = {get-gui-manager}
    
    {gui-manager.add-event-handler
        {on e:KeyPress do
            
            {if-non-null active-tf:AutoCompleteTextField = AutoCompleteTextField.active-tf
             then
                {active-tf.handle-key-event-on-menu e}
            }
        }
    }
    
    set AutoCompleteTextField.init? = true
  }
  
  {getter private {has-focus?}:bool
    
    let focus-manager:#FocusManager = {self.get-focus-manager}
    
    {return
        (focus-manager != null)
        and (focus-manager.keyboard-focus-target == self.ui-object)
    }
  }
  
  {method protected {show-menu}:void
    
    {if-non-null self.menu-pane
     then
        {self.expand-menu}
        {return}
    }
    
    
    {if (not self.has-focus?) or (self._proposed-values) == null
     then
        {if-non-null self.menu-pane
         then
            {self.hide-menu}
        }
        
        {return}
    }
    
    set AutoCompleteTextField.active-tf = self
    
    {self.expand-menu}
    
  }
  
  {method private {expand-menu}:void
    
    {if-non-null self.menu-pane
     then
        {self.menu-pane.hide}
    }
    
    set self.menu-pane =
        {DropdownMenuPane
            background = "transparent",
            control-color = "white",
            use-look-and-feel? = false,
            menu-height = self._menu-height,
            {on DetachEvent do
                {if not self.has-focus?
                 then
                    set self.menu-pane = null
                }
            }
        }
    
    let filter-values:{Array-of String} =
        {self.proposed-values.filter-clone
            {proc {str:String}:bool
                {return
                    || fixed by Akira Mori
                    ||{str.prefix? self.value}
                    {str.prefix? self.value, ignore-case? = self.ignore-case?}
                }
            }
        }
    
    {if filter-values.size == 1
     then
        let candidate-value:String = filter-values[0]
        {if candidate-value == self.value
         then
            {self.hide-menu}
            {return}
        }
     elseif filter-values.empty?
     then
        {self.hide-menu}
        {return}
    }
    
    {self.menu-pane.clear}
    
    {for str:String in filter-values do
        {self.menu-pane.add
            {MenuAction
                label = str,
                {on Action do
                    {self.set-value-with-events str}
                    {self.hide-menu}
                    set AutoCompleteTextField.active-tf = null
                }
            }
        }
    }
    
    {self.menu-pane.show-adjacent
        self,
        alongside? = false,
        {self.layout.get-bounds},
        start-traversal? = true
    }
    
||--    {self.menu-pane.request-key-focus}
  }
  
  {method protected {hide-menu}:void
    
    {if self.menu-pane == null
     then
        {return}
    }
    
    {self.menu-pane.hide}
    
    set self.menu-pane = null
    set AutoCompleteTextField.active-tf = null
    
  }
  
  {getter public {proposed-values}:#{Array-of String}
    {return self._proposed-values}
  }
  
  {setter public {proposed-values proposed-values:#{Array-of String}}:void
    set  self._proposed-values = proposed-values
  }
  
  {method protected {handle-key-event-on-menu e:KeyPress}:void
    
    {if not e.insertable?
     then
        {switch e.value
         case KeyPressValue.up,KeyPressValue.down do
            {self.menu-pane.handle-event e}
         case KeyPressValue.esc do
            set AutoCompleteTextField.active-tf = null
         case KeyPressValue.tab do
            set AutoCompleteTextField.active-tf = null
            {self.hide-menu}
            {self.ui-object.on-key-press e}
         case KeyPressValue.backspace do
            {self.ui-object.handle-event e}
        }
        
        {return}
     else
        {switch e.value
         case KeyPressValue.backspace do
            {self.ui-object.on-key-press e}
            
            {return}
        }
        
    }
    
 
    {self.set-value-with-events self.value&e.value}
 
  }
  
  {method public {on-key-press e:KeyPress}:void
    {switch e.value
     case KeyPressValue.down do
        {self.show-menu}
    }
    {super.on-key-press e}
  }
}
{AutoCompleteTextField
    height = 1cm,
    font-size = 1cm,
    proposed-values =
        {{Array-of String}
            "aaa",
            "aab",
            "abc",
            "abd",
            "abe",
            "abf",
            "bbb",
            "ccc",
            "ddd",
            "eee",
            "fff"
                 }
    
}


please give your suggestion.

Thanks in advance :)

Regards,
Mannusanghi
Click to view Kamal's profile Curl Kamal 139 posts since
Oct 17, 2007
1. Re: Want to use AutoComplete TextField with multiple values. Oct 3, 2008 7:39 AM
Sorry, I did not understand your question. Do you mean that you should be able to select more than one value from the drop down pane?
Click to view mannusanghi's profile Level 2 mannusanghi 28 posts since
Feb 27, 2008
2. Re: Want to use AutoComplete TextField with multiple values. Oct 3, 2008 9:43 PM
in response to: Kamal

HI kamal,

Yes I want to select multiple values for textfield. but one at a time.

Like compare to this example i want these values like AAA,BBB,CCC

for example when i type 'a' then it will show All 'a' list after that when i write ', "after 'a' and type "b" then i again want to show menu pane with All "b" list so on.

So i can say that i want to populate menu pane after "," and select value from menu pane this will append to exixting textfield value.


Thanks in Advance :)

Regards,

Mannusanghi

Click to view Kamal's profile Curl Kamal 139 posts since
Oct 17, 2007
3. Re: Want to use AutoComplete TextField with multiple values. Oct 4, 2008 9:00 AM
in response to: mannusanghi
There are few things that you will have to do to make this work.

1. Decide what should be considered word boundaries. Empty spaces, full stop, comma, semicolon etc.
2. When a call to expand menu is called, you will have to get the current cursor position. From it you can decide what part of the TextField value you should use for filtering the data and to show the matches, if any, in the menu pane. Remember, in the current code it uses the entire text field's current value.
3. The next important part will be to insert the current selected item in menu w.r.t. the cursor position in the text field.