Class: Clevic::ComboDelegate
- Defined in:
- lib/clevic/qt/combo_delegate.rb,
lib/clevic/swing/combo_delegate.rb,
lib/clevic/delegates/combo_delegate.rb
Overview
TODO this should be a module
Direct Known Subclasses
Instance Attribute Summary collapse
-
#editor ⇒ Object
readonly
Return the GUI component / widget that is displayed when editing.
Attributes inherited from Delegate
Instance Method Summary collapse
-
#allow_null? ⇒ Boolean
TODO fetch this from the model definition.
-
#autocomplete(&block) ⇒ Object
make sure we don’t react to document change events while we’re doing autocompletion.
- #combo_class ⇒ Object
-
#configure_editable ⇒ Object
TODO kinda redundant because all combos must be editable to support prefix matching.
-
#configure_prefix ⇒ Object
Some GUIs (Qt) can just set this.
- #create_combo_box(*args) ⇒ Object
-
#createEditor(parent_widget, style_option_view_item, model_index) ⇒ Object
Override the Qt method.
-
#display_for(model_value) ⇒ Object
Return a string to be shown to the user.
- #dump_editor_state(editor) ⇒ Object
-
#empty_set? ⇒ Boolean
return true if this field has no data (needs_combo? is false) and is at the same time restricted (ie needs data from somewhere else).
-
#filter_prefix(prefix) ⇒ Object
www.drdobbs.com/184404457 for autocompletion steps.
- #framework_setup(*args) ⇒ Object
-
#full_edit ⇒ Object
open the combo box, just like if F4 was pressed big trouble here with JComboBox firing an comboEdited action (probably) on focusGained which causes the popup to be hidden again.
-
#getListCellRendererComponent(jlist, value, index, selected, cell_has_focus) ⇒ Object
return the component to render the values in the list we just transform the value, and pass it to the pre-existing renderer for the combo.
-
#hint_string(hint) ⇒ Object
- Convert Qt
-
constants from the integer value to a string value.
-
#if_empty_message ⇒ Object
if this delegate has an empty set, return the message, otherwise return nil.
-
#init_component(*args) ⇒ Object
Create a GUI widget and fill it with the possible values.
-
#initialize(field) ⇒ ComboDelegate
constructor
A new instance of ComboDelegate.
- #is_combo? ⇒ Boolean
-
#line_editor(value) ⇒ Object
return a new text editor.
-
#minimal_edit ⇒ Object
show only the text editor part, not the drop-down.
-
#needs_pre_selection? ⇒ Boolean
the cell must be selected before the edit can be clicked.
-
#repopulate(prefix = nil, text = nil) ⇒ Object
Recreate the model and fill it with anything in population that matches the prefix first, followed by anything in the population that doesn’t match the prefix.
-
#restricted? ⇒ Boolean
returns true if the editor allows values outside of a predefined range, false otherwise.
-
#setEditorData(editor, model_index) ⇒ Object
Override the Qt method to send data to the editor from the model.
-
#setModelData(editor, abstract_item_model, model_index) ⇒ Object
Send the data from the editor to the model.
-
#translate_from_editor_text(editor, text) ⇒ Object
This translates the text from the editor into something that is stored in an underlying model.
-
#updateEditorGeometry(editor, style_option_view_item, model_index) ⇒ Object
Override the Qt::ItemDelegate method.
- #value ⇒ Object
Methods inherited from Delegate
#attribute, #editorEvent, #entity_class, #inspect, #native, #show_message
Methods included from FieldValuer
#attribute_value, #attribute_value=, #display_value, #edit_value, #edit_value=, #find_related, #raw_value, #text_value=, #tooltip, valuer, #valuer, #writer
Constructor Details
#initialize(field) ⇒ ComboDelegate
Returns a new instance of ComboDelegate.
58 59 60 61 |
# File 'lib/clevic/swing/combo_delegate.rb', line 58 def initialize( field ) super @autocompleting = false end |
Instance Attribute Details
#editor ⇒ Object (readonly)
Return the GUI component / widget that is displayed when editing. Usually this will be a combo box widget, but it can be a text editor in some cases. if editor is a combo it must support no_insert=( bool )
14 15 16 |
# File 'lib/clevic/delegates/combo_delegate.rb', line 14 def editor @editor end |
Instance Method Details
#allow_null? ⇒ Boolean
TODO fetch this from the model definition
112 113 114 |
# File 'lib/clevic/delegates/combo_delegate.rb', line 112 def allow_null? true end |
#autocomplete(&block) ⇒ Object
make sure we don’t react to document change events while we’re doing autocompletion. Reentrant
174 175 176 177 178 179 |
# File 'lib/clevic/swing/combo_delegate.rb', line 174 def autocomplete( &block ) @autocompleting = true yield ensure @autocompleting = false end |
#combo_class ⇒ Object
63 64 65 |
# File 'lib/clevic/swing/combo_delegate.rb', line 63 def combo_class ComboBox end |
#configure_editable ⇒ Object
TODO kinda redundant because all combos must be editable to support prefix matching
28 29 30 |
# File 'lib/clevic/delegates/combo_delegate.rb', line 28 def configure_editable editor.editable = true end |
#configure_prefix ⇒ Object
Some GUIs (Qt) can just set this. Swing can’t.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/clevic/swing/combo_delegate.rb', line 104 def configure_prefix # pick up events from editor # but only after all the other config, otherwise we get # events triggered by the setup, which isn't helpful. editor.editor.editor_component.document.add_document_listener do |event| # don't do anything if autocomplete manipulations are in progress unless @autocompleting || !editor.typing if event.type == javax.swing.event.DocumentEvent::EventType::REMOVE invoke_later do repopulate end else # only suggest on inserts and updates. Not on deletes. filter_prefix( editor.editor.item ) end end end end |
#create_combo_box(*args) ⇒ Object
46 47 48 49 50 51 |
# File 'lib/clevic/qt/combo_delegate.rb', line 46 def create_combo_box( *args ) Qt::ComboBox.new( parent ).tap do |combo| # all combos are editable so that prefix matching will work combo.editable = true end end |
#createEditor(parent_widget, style_option_view_item, model_index) ⇒ Object
Override the Qt method. Create a ComboBox widget and fill it with the possible values.
54 55 56 57 58 59 60 |
# File 'lib/clevic/qt/combo_delegate.rb', line 54 def createEditor( , style_option_view_item, model_index ) self.parent = self.entity = model_index.entity init_component( , style_option_view_item, model_index ) editor.delegate = self editor end |
#display_for(model_value) ⇒ Object
Return a string to be shown to the user. model_value is an item stored in the combo box model.
18 19 20 |
# File 'lib/clevic/delegates/combo_delegate.rb', line 18 def display_for( model_value ) field.transform_attribute( model_value ) end |
#dump_editor_state(editor) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/clevic/qt/combo_delegate.rb', line 23 def dump_editor_state( editor ) if $options[:debug] puts "#{self.class.name}" puts "editor.completer.completion_count: #{editor.completer.completion_count}" puts "editor.completer.current_completion: #{editor.completer.current_completion}" puts "editor.find_text( editor.completer.current_completion ): #{editor.find_text( editor.completer.current_completion )}" puts "editor.current_text: #{editor.current_text}" puts "editor.count: #{editor.count}" puts "editor.completer.current_row: #{editor.completer.current_row}" puts "editor.item_data( editor.current_index ): #{editor.item_data( editor.current_index ).inspect}" puts end end |
#empty_set? ⇒ Boolean
return true if this field has no data (needs_combo? is false) and is at the same time restricted (ie needs data from somewhere else)
135 136 137 |
# File 'lib/clevic/delegates/combo_delegate.rb', line 135 def empty_set? !needs_combo? && restricted? end |
#filter_prefix(prefix) ⇒ Object
www.drdobbs.com/184404457 for autocompletion steps
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/clevic/swing/combo_delegate.rb', line 182 def filter_prefix( prefix ) # search for matching item in the UI display_for for the items in the combo model candidate = population.map{|item| display_for( item ) }.select {|x| x =~ /^#{prefix}/i }.first unless candidate.nil? first_not_of = candidate.match( /^#{prefix}/i ).offset(0).last invoke_later do autocomplete do # set the shortlist, and the text editor value repopulate prefix, candidate # set the suggestion selection editor.editor.editor_component.with do |text_edit| # highlight the suggested match, and leave caret # at the beginning of the suggested text text_edit.caret_position = candidate.length text_edit.move_caret_position( first_not_of ) end end end end end |
#framework_setup(*args) ⇒ Object
66 67 68 69 |
# File 'lib/clevic/qt/combo_delegate.rb', line 66 def framework_setup( *args ) # don't need to do anything here # might need to once prefix-matching is implemented end |
#full_edit ⇒ Object
open the combo box, just like if F4 was pressed big trouble here with JComboBox firing an comboEdited action (probably) on focusGained which causes the popup to be hidden again
38 39 40 |
# File 'lib/clevic/qt/combo_delegate.rb', line 38 def full_edit editor.show_popup if is_combo?( editor ) end |
#getListCellRendererComponent(jlist, value, index, selected, cell_has_focus) ⇒ Object
return the component to render the values in the list we just transform the value, and pass it to the pre-existing renderer for the combo.
90 91 92 |
# File 'lib/clevic/swing/combo_delegate.rb', line 90 def getListCellRendererComponent(jlist, value, index, selected, cell_has_focus) @original_renderer.getListCellRendererComponent(jlist, display_for( value ), index, selected, cell_has_focus) end |
#hint_string(hint) ⇒ Object
- Convert Qt
-
constants from the integer value to a string value.
TODO this really shouldn’t be here. qtext, or extensions.rb
15 16 17 18 19 20 21 |
# File 'lib/clevic/qt/combo_delegate.rb', line 15 def hint_string( hint ) hs = String.new Qt::AbstractItemDelegate.constants.each do |x| hs = x if eval( "Qt::AbstractItemDelegate::#{x}.to_i" ) == hint.to_i end hs end |
#if_empty_message ⇒ Object
if this delegate has an empty set, return the message, otherwise return nil.
145 146 147 |
# File 'lib/clevic/delegates/combo_delegate.rb', line 145 def if empty_set? end |
#init_component(*args) ⇒ Object
Create a GUI widget and fill it with the possible values. *args will be passed as-is to framework_setup NOTE RIght now it’s the framework’s responsibility to call
self.entity = some_entity
There must be a good way to check that though.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/clevic/delegates/combo_delegate.rb', line 58 def init_component( *args ) if needs_combo? @editor = create_combo_box( *args ) @editor.delegate = self # add all entries from population population.each do |item| editor << item end # create a nil entry if necessary if allow_null? && !editor.include?( nil ) editor << nil end # don't allow inserts if the delegate is restricted editor.no_insert = restricted? # set the correct value in the list editor.selected_item = entity.nil? ? nil : attribute_value # set up prefix matching when typing in the editor configure_prefix framework_setup( *args ) else @editor = if restricted? ( ) nil else # there is no data yet for the combo, and it's # not restricted, so just edit with a simple text field. line_editor( edit_value ) end end editor end |
#is_combo? ⇒ Boolean
42 43 44 |
# File 'lib/clevic/qt/combo_delegate.rb', line 42 def is_combo?( editor ) editor.is_a?( Qt::ComboBox ) end |
#line_editor(value) ⇒ Object
return a new text editor. This is for distinct_delegate when there are no other values to choose from. TODO move into distinct_delegate then?
97 98 99 |
# File 'lib/clevic/swing/combo_delegate.rb', line 97 def line_editor( edit_value ) @line_editor ||= Qt::LineEdit.new( edit_value, parent ) end |
#minimal_edit ⇒ Object
show only the text editor part, not the drop-down
221 222 223 |
# File 'lib/clevic/swing/combo_delegate.rb', line 221 def minimal_edit editor.hide_popup if is_combo? end |
#needs_pre_selection? ⇒ Boolean
the cell must be selected before the edit can be clicked
68 69 70 |
# File 'lib/clevic/swing/combo_delegate.rb', line 68 def needs_pre_selection? true end |
#repopulate(prefix = nil, text = nil) ⇒ Object
Recreate the model and fill it with anything in population that matches the prefix first, followed by anything in the population that doesn’t match the prefix. Then set the editor text value to either text, or to the previous value. Order is important: if the text is set first it’s overridden when the model is populated.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/clevic/swing/combo_delegate.rb', line 152 def repopulate( prefix = nil, text = nil ) autocomplete do # save text and popup save_item = editor.editor.item dropdown_visible = editor.popup_visible? # repopulate based on the prefix prefix ||= editor.editor.item editor.model = editor.model.class.new # split set into things to display at the top, and things to display further down matching, non_matching = population.partition{ |item| display_for( item ) =~ /^#{prefix}/i } matching.each {|item| editor << item} non_matching.each {|item| editor << item} # restore text and popup editor.editor.item = text || save_item editor.popup_visible = dropdown_visible end end |
#restricted? ⇒ Boolean
returns true if the editor allows values outside of a predefined range, false otherwise.
107 108 109 |
# File 'lib/clevic/delegates/combo_delegate.rb', line 107 def restricted? false end |
#setEditorData(editor, model_index) ⇒ Object
Override the Qt method to send data to the editor from the model.
82 83 84 85 86 87 88 89 |
# File 'lib/clevic/qt/combo_delegate.rb', line 82 def setEditorData( editor, model_index ) if is_combo?( editor ) editor.current_index = editor.find_data( model_index.attribute_value.to_variant ) editor.line_edit.select_all if editor.editable else editor.text = model_index.edit_value end end |
#setModelData(editor, abstract_item_model, model_index) ⇒ Object
Send the data from the editor to the model. The data will be translated by translate_from_editor_text,
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/clevic/qt/combo_delegate.rb', line 105 def setModelData( editor, abstract_item_model, model_index ) if is_combo?( editor ) dump_editor_state( editor ) value = if editor.completer.current_row == -1 # item doesn't exist in the list, add it if not restricted editor.current_text unless restricted? elsif editor.completer.completion_count == editor.count # selection from drop down. if it's empty, we want a nil editor.current_text else # there is a matching completion, so use it editor.completer.current_completion end if value != nil model_index.attribute_value = translate_from_editor_text( editor, value ) end else model_index.attribute_value = editor.text end abstract_item_model.data_changed( model_index ) end |
#translate_from_editor_text(editor, text) ⇒ Object
This translates the text from the editor into something that is stored in an underlying model. Intended to be overridden by subclasses.
93 94 95 96 97 98 99 100 101 |
# File 'lib/clevic/qt/combo_delegate.rb', line 93 def translate_from_editor_text( editor, text ) index = editor.find_text( text ) if index == -1 text unless restricted? else editor.item_data( index ).value end end |
#updateEditorGeometry(editor, style_option_view_item, model_index) ⇒ Object
Override the Qt::ItemDelegate method.
72 73 74 75 76 77 78 79 |
# File 'lib/clevic/qt/combo_delegate.rb', line 72 def updateEditorGeometry( editor, style_option_view_item, model_index ) rect = style_option_view_item.rect # ask the editor for how much space it wants, and set the editor # to that size when it displays in the table rect.set_width( [editor.size_hint.width,rect.width].max ) if is_combo?( editor ) editor.set_geometry( rect ) end |
#value ⇒ Object
231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/clevic/swing/combo_delegate.rb', line 231 def value # editor could be either a combo or a line (DistinctDelegate with no values yet) if is_combo? if restricted? editor.selected_item else editor.editor.item end else puts "#{__FILE__}:#{__LINE__}:line item value: #{editor.text}. Take this away when it's printed." editor.text end end |