# # # patch "lib/perl/AdvancedFind.pm" # from [2710ba47e3cf4d8cb6d3acb421cb518491056f49] # to [be8cc22c57fa7fde3f67a8bf55b97b55de6e49be] # # patch "lib/perl/ComboAutoCompletion.pm" # from [a08dd9dab70a34a5e71ccb6b35a16d2861894521] # to [dd0811843a29ab6bca6301bb1091987c98f3a75d] # # patch "lib/perl/MultipleRevisions.pm" # from [9dc8cc9e3f7d7c0f4262eaddeaf4913c0b425bf7] # to [468faa0c856b67fc9f034bf03bcde08d8adf0edd] # # patch "lib/ui/mtn-browse.glade" # from [f6f29a1bebcf6a7b88fe72f9de8163a7719aed80] # to [2c32f821449107cb7519688a866854127f24e11c] # # patch "mtn-browse" # from [e9beceba6af5e7e6dcfb9142bbf79456597d2a44] # to [142c65ac8cd6a27d25dae7b21398bd2f18d16f6e] # ============================================================ --- lib/perl/AdvancedFind.pm 2710ba47e3cf4d8cb6d3acb421cb518491056f49 +++ lib/perl/AdvancedFind.pm be8cc22c57fa7fde3f67a8bf55b97b55de6e49be @@ -606,7 +606,7 @@ sub get_advanced_find_window($) $instance->{stop_button}->signal_connect ("clicked", sub { $_[1]->{stop} = 1; }, $instance); - # Setup the empty comboboxes. + # Setup the comboboxes. $instance->{branch_comboboxentry}-> set_model(Gtk2::ListStore->new("Glib::String")); @@ -739,6 +739,13 @@ sub get_advanced_find_window($) $instance->{revision_combo_details}->{preset} = 0; &{$instance->{update_handler}}($instance, NEW_FIND); + # Now the advanced find instance is completely initialised, set up the + # branch and revision comboboxentry widgets for auto-completion. + + activate_auto_completion($instance->{branch_comboboxentry}, $instance); + activate_auto_completion($instance->{revision_comboboxentry}, + $instance); + } else { ============================================================ --- lib/perl/ComboAutoCompletion.pm a08dd9dab70a34a5e71ccb6b35a16d2861894521 +++ lib/perl/ComboAutoCompletion.pm dd0811843a29ab6bca6301bb1091987c98f3a75d @@ -47,63 +47,160 @@ use warnings; use strict; use warnings; +# ***** GLOBAL DATA DECLARATIONS ***** + +# The type of window that is going to be managed by this module. + +my $window_type = "tooltip_window"; + # ***** FUNCTIONAL PROTOTYPES ***** # Public routines. -sub comboboxentry_changed_cb($$); -sub comboboxentry_key_release_event_cb($$$); +sub activate_auto_completion($$); sub tagged_checkbutton_toggled_cb($$); + +# Private routines. + +sub auto_completion_comboboxentry_changed_cb($$); +sub auto_completion_comboboxentry_key_release_event_cb($$$); +sub get_tooltip_window($$$$); +sub hide_tooltip_window(); # ############################################################################## # -# Routine - comboboxentry_changed_cb +# Routine - activate_auto_completion # -# Description - Callback routine called when the user changes the value of -# a branch or revision comboboxentry by selecting an entry -# from its pulldown list. +# Description - Sets up the specified comboboxentry widget for +# auto-completion. # -# Data - $widget : The widget object that received the signal. -# $instance : The window instance that is associated with -# this widget. +# Data - $comboboxentry : The comboboxentry widget that is to be set +# up for auto-completion. +# $instance : The window instance that is associated +# with this widget. It is expected to have +# window, appbar, update_handler and +# combobox details fields. # ############################################################################## -sub comboboxentry_changed_cb($$) +sub activate_auto_completion($$) { - my($widget, $instance) = @_; + my($comboboxentry, $instance) = @_; - return if ($instance->{in_cb}); - local $instance->{in_cb} = 1; - my($change_state, $combo_details, - $item, - $value); + $details, + $name); - if ($widget == $instance->{branch_comboboxentry}) + # Sort out the precise details depending upon which comboboxentry widget + # has been passed. + + if ($comboboxentry == $instance->{branch_comboboxentry}) { $change_state = BRANCH_CHANGED; $combo_details = $instance->{branch_combo_details}; + $name = __("branch"); } - elsif ($widget == $instance->{revision_comboboxentry}) + elsif ($comboboxentry == $instance->{revision_comboboxentry}) { $change_state = REVISION_CHANGED; $combo_details = $instance->{revision_combo_details}; + $name = __("revision"); } - elsif ($widget == $instance->{directory_comboboxentry}) + elsif ($comboboxentry == $instance->{directory_comboboxentry}) { $change_state = DIRECTORY_CHANGED; $combo_details = $instance->{directory_combo_details}; + $name = __("directory"); } else { return; } + # Set up all the required callbacks. + + $details = {instance => $instance, + change_state => $change_state, + combo_details => $combo_details, + name => $name}; + $comboboxentry->signal_connect("changed", + \&auto_completion_comboboxentry_changed_cb, + $details); + $comboboxentry->signal_connect + ("key_release_event", + \&auto_completion_comboboxentry_key_release_event_cb, + $details); + $comboboxentry->child()->signal_connect("focus_out_event", + sub { + hide_tooltip_window(); + return FALSE; + }); + +} +# +############################################################################## +# +# Routine - tagged_checkbutton_toggled_cb +# +# Description - Callback routine called when the user changes the value of +# the tagged check button. +# +# Data - $widget : The widget object that received the signal. +# $instance : The window instance that is associated with +# this widget. +# +############################################################################## + + + +sub tagged_checkbutton_toggled_cb($$) +{ + + my($widget, $instance) = @_; + + return if ($instance->{in_cb}); + local $instance->{in_cb} = 1; + + $instance->{appbar}->clear_stack(); + &{$instance->{update_handler}}($instance, BRANCH_CHANGED); + +} +# +############################################################################## +# +# Routine - auto_completion_comboboxentry_changed_cb +# +# Description - Callback routine called when the user changes the value of +# a branch, revision or directory comboboxentry by selecting +# an entry from its pulldown list. +# +# Data - $widget : The widget object that received the signal. +# $details : A reference to an anonymous hash containing the +# window instance, change state, comboboxentry +# details and the name for that comboboxentry. +# +############################################################################## + + + +sub auto_completion_comboboxentry_changed_cb($$) +{ + + my($widget, $details) = @_; + + my $instance = $details->{instance}; + + return if ($instance->{in_cb}); + local $instance->{in_cb} = 1; + + my $value; + my $change_state = $details->{change_state}; + my $combo_details = $details->{combo_details}; + # For some reason best known to itself, Gtk+ calls this callback when the # user presses a key for the first time (but not subsequently) after a # value is selected via the pulldown menu. So we have to guard against @@ -112,7 +209,7 @@ sub comboboxentry_changed_cb($$) # direct match to one in our list. $value = $widget->child()->get_text(); - foreach $item (@{$combo_details->{list}}) + foreach my $item (@{$combo_details->{list}}) { if ($value eq $item) { @@ -120,6 +217,7 @@ sub comboboxentry_changed_cb($$) $combo_details->{complete} = 1; $instance->{appbar}->clear_stack(); &{$instance->{update_handler}}($instance, $change_state); + hide_tooltip_window(); last; } } @@ -128,7 +226,7 @@ sub comboboxentry_changed_cb($$) # ############################################################################## # -# Routine - comboboxentry_key_release_event_cb +# Routine - auto_completion_comboboxentry_key_release_event_cb # # Description - Callback routine called when the user changes the value of # a branch or revision comboboxentry by entering a character @@ -137,8 +235,10 @@ sub comboboxentry_changed_cb($$) # Data - $widget : The widget object that received the signal. # $event : A Gtk2::Gdk::Event object describing the # event that has occurred. -# $instance : The window instance that is associated with -# this widget. +# $details : A reference to an anonymous hash containing +# the window instance, change state, +# comboboxentry details and the name for that +# comboboxentry. # Return Value : TRUE if the event has been handled and needs # no further handling, otherwise false if the # event should carry on through the remaining @@ -148,55 +248,29 @@ sub comboboxentry_changed_cb($$) -sub comboboxentry_key_release_event_cb($$$) +sub auto_completion_comboboxentry_key_release_event_cb($$$) { - my($widget, $event, $instance) = @_; + my($widget, $event, $details) = @_; + my $instance = $details->{instance}; + return FALSE if ($instance->{in_cb}); local $instance->{in_cb} = 1; - my($change_state, - $combo, - $combo_details, - $complete, + my($complete, $completion, - $entry, $item, $len, - $name, $old_complete, $old_value, $success, $value); + my $change_state = $details->{change_state}; + my $combo_details = $details->{combo_details}; + my $entry = $widget->child(); + my $name = $details->{name}; - if ($widget == $instance->{branch_comboboxentry}) - { - $combo = $instance->{branch_comboboxentry}; - $change_state = BRANCH_CHANGED; - $combo_details = $instance->{branch_combo_details}; - $name = __("branch"); - } - elsif ($widget == $instance->{revision_comboboxentry}) - { - $combo = $instance->{revision_comboboxentry}; - $change_state = REVISION_CHANGED; - $combo_details = $instance->{revision_combo_details}; - $name = __("revision"); - } - elsif ($widget == $instance->{directory_comboboxentry}) - { - $combo = $instance->{directory_comboboxentry}; - $change_state = DIRECTORY_CHANGED; - $combo_details = $instance->{directory_combo_details}; - $name = __("directory"); - } - else - { - return FALSE; - } - $entry = $widget->child(); - # The user has typed something in then validate it and auto-complete it if # necessary. @@ -237,12 +311,37 @@ sub comboboxentry_key_release_event_cb($ if ($success) { $instance->{appbar}->clear_stack(); + hide_tooltip_window(); } else { - $instance->{appbar}->push(__x("Invalid {name} name `{value}'", - name => $name, - value => $value)); + + my($height, + $message, + $root_x, + $root_y, + $x, + $y); + + # Tell the user what is wrong via the status bar. + + $message = __x("Invalid {name} name `{value}'", + name => $name, + value => $value); + $instance->{appbar}->push($message); + + # Also via a tooltip as well (need to position it to be just + # below the comboboxentry widget). + + ($x, $y) = + $widget->translate_coordinates($instance->{window}, 0, 0); + $height = ($widget->child()->window()->get_geometry())[3]; + ($root_x, $root_y) = + $instance->{window}->window()->get_origin(); + $x += $root_x - 10; + $y += $height + $root_y + 5; + get_tooltip_window($instance->{window}, $message, $x, $y); + } $value = $completion; $len = length($value); @@ -253,6 +352,7 @@ sub comboboxentry_key_release_event_cb($ else { $instance->{appbar}->clear_stack(); + hide_tooltip_window(); } $combo_details->{value} = $value; $combo_details->{complete} = $complete; @@ -261,10 +361,10 @@ sub comboboxentry_key_release_event_cb($ if (! $user_preferences->{static_lists}) { - $combo->get_model()->clear(); + $widget->get_model()->clear(); foreach $item (@{$combo_details->{list}}) { - $combo->append_text($item) + $widget->append_text($item) if ($value eq substr($item, 0, $len)); # The following check is needed in the case when the user is @@ -289,30 +389,141 @@ sub comboboxentry_key_release_event_cb($ # ############################################################################## # -# Routine - tagged_checkbutton_toggled_cb +# Routine - get_tooltip_window # -# Description - Callback routine called when the user changes the value of -# the tagged check button. +# Description - Creates or prepares an existing tooltip window for use. # -# Data - $widget : The widget object that received the signal. -# $instance : The window instance that is associated with -# this widget. +# Data - $parent : The parent window widget for the multiple +# revisions dialog window. +# $message : The tooltip that is to be displayed. +# $x : The x coordinate for where the tooltip +# window is to be placed. +# $y : The y coordinate for where the tooltip +# window is to be placed. +# Return Value : A reference to the newly created or unused +# multiple revisions instance record. # ############################################################################## -sub tagged_checkbutton_toggled_cb($$) +sub get_tooltip_window($$$$) { - my($widget, $instance) = @_; + my($parent, $message, $x, $y) = @_; - return if ($instance->{in_cb}); + my($instance, + $new); + my $wm = WindowManager->instance(); + + # Create a new tooltip window if an existing one wasn't found, otherwise + # reuse an existing unused one. + + if (! defined($instance = $wm->cond_find($window_type, sub { return 1; }))) + { + + $new = 1; + $instance = {}; + $instance->{glade} = Gtk2::GladeXML->new($glade_file, + $window_type, + APPLICATION_NAME); + + # Flag to stop recursive calling of callbacks. + + $instance->{in_cb} = 0; + local $instance->{in_cb} = 1; + + # Connect Glade registered signal handlers. + + glade_signal_autoconnect($instance->{glade}, $instance); + + # Get the widgets that we are interested in. + + $instance->{window} = $instance->{glade}->get_widget($window_type); + foreach my $widget ("eventbox", "message_label") + { + $instance->{$widget} = $instance->{glade}->get_widget($widget); + } + + # Setup the colours used for the tooltip window. + + $instance->{window}->modify_bg("normal", + Gtk2::Gdk::Color->parse("Black")); + $instance->{eventbox}->modify_bg("normal", + Gtk2::Gdk::Color->parse("Pink")); + + } + else + { + $instance->{in_cb} = 0; + local $instance->{in_cb} = 1; + $instance->{window}->hide(); + Glib::Source->remove($instance->{timeout_source_id}); + } + local $instance->{in_cb} = 1; - $instance->{appbar}->clear_stack(); - &{$instance->{update_handler}}($instance, BRANCH_CHANGED); + # Update the tooltip message text and setup a timout handler to dismiss the + # window after three seconds. + $instance->{message_label}->set_text($message); + $instance->{timeout_source_id} = + Glib::Timeout->add(3000, + sub { + my $instance = $_[0]; + $instance->{window}->hide(); + return FALSE; + }, + $instance); + + # Position it, reparent window and display it. + + $instance->{window}->move($x, $y); + $instance->{window}->set_transient_for($parent); + $instance->{window}->show_all(); + $instance->{window}->present(); + + # If necessary, register the window for management. + + $wm->manage($instance, $window_type, $instance->{window}) if ($new); + + return $instance; + } +# +############################################################################## +# +# Routine - hide_tooltip_window +# +# Description - Hides the tooltip window if it is visible. +# +# Data - None. +# +############################################################################## + + +sub hide_tooltip_window() +{ + + my $instance; + + # Look for a mapped tooltip window, if found then hide it and cancel its + # hide timeout handler. + + if (defined($instance = WindowManager->instance()->cond_find + ($window_type, + sub { + my $instance = $_[0]; + return $instance->{window}->mapped(); + }))) + { + $instance->{in_cb} = 0; + local $instance->{in_cb} = 1; + $instance->{window}->hide(); + Glib::Source->remove($instance->{timeout_source_id}); + } + +} + 1; ============================================================ --- lib/perl/MultipleRevisions.pm 9dc8cc9e3f7d7c0f4262eaddeaf4913c0b425bf7 +++ lib/perl/MultipleRevisions.pm 468faa0c856b67fc9f034bf03bcde08d8adf0edd @@ -54,7 +54,7 @@ sub multiple_revisions_selection($$$@); # Private routines. -sub get_multiple_revisions_window($$@); +sub get_multiple_revisions_window($); # ############################################################################## # @@ -88,9 +88,22 @@ sub multiple_revisions_selection($$$@) my($instance, $response); - $instance = get_multiple_revisions_window($parent, - $message, - @revision_ids); + $instance = get_multiple_revisions_window($parent); + local $instance->{in_cb} = 1; + + # Update the message text and the revisions combobox with the supplied + # information. + + $instance->{message_label}->set_markup($message); + $instance->{revisions_combobox}->get_model()->clear(); + foreach my $revision_id (@revision_ids) + { + $instance->{revisions_combobox}->append_text($revision_id); + } + $instance->{revisions_combobox}->set_active(0); + + # Wait for the user to respond. + WindowManager->instance()->allow_input (sub { $response = $instance->{window}->run(); }); $instance->{window}->hide(); @@ -124,9 +137,6 @@ sub multiple_revisions_selection($$$@) # # Data - $parent : The parent window widget for the multiple # revisions dialog window. -# $message : The message that is to be displayed. -# @revision_ids : A list of revision ids that the user is to -# select from. # Return Value : A reference to the newly created or unused # multiple revisions instance record. # @@ -134,10 +144,10 @@ sub multiple_revisions_selection($$$@) -sub get_multiple_revisions_window($$@) +sub get_multiple_revisions_window($) { - my($parent, $message, @revision_ids) = @_; + my $parent = $_[0]; my($instance, $new); @@ -191,17 +201,6 @@ sub get_multiple_revisions_window($$@) local $instance->{in_cb} = 1; - # Update the message text and the revisions combobox with the supplied - # information. - - $instance->{message_label}->set_markup($message); - $instance->{revisions_combobox}->get_model()->clear(); - foreach my $revision_id (@revision_ids) - { - $instance->{revisions_combobox}->append_text($revision_id); - } - $instance->{revisions_combobox}->set_active(0); - # Reparent window and display it. $instance->{window}->set_transient_for($parent); ============================================================ --- lib/ui/mtn-browse.glade f6f29a1bebcf6a7b88fe72f9de8163a7719aed80 +++ lib/ui/mtn-browse.glade 2c32f821449107cb7519688a866854127f24e11c @@ -510,8 +510,6 @@ True - - 0 @@ -571,8 +569,6 @@ True - - 0 @@ -849,8 +845,6 @@ in Monotone-Viz True - - 0 @@ -2390,8 +2384,6 @@ specify very specific selection critia True - - 0 @@ -2451,8 +2443,6 @@ specify very specific selection critia True - - 0 @@ -9440,4 +9430,43 @@ that you want + + + GTK_WINDOW_POPUP + GTK_WIN_POS_NONE + False + False + False + False + True + True + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + 1 + True + True + False + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 5 + 5 + + + + + + ============================================================ --- mtn-browse e9beceba6af5e7e6dcfb9142bbf79456597d2a44 +++ mtn-browse 142c65ac8cd6a27d25dae7b21398bd2f18d16f6e @@ -1648,14 +1648,14 @@ sub get_browser_window(;$$$$$) set_model(Gtk2::ListStore->new("Glib::String")); $browser->{branch_comboboxentry}->set_text_column(0); $browser->{branch_comboboxentry}->set_wrap_width(2); + $browser->{revision_comboboxentry}-> + set_model(Gtk2::ListStore->new("Glib::String")); + $browser->{revision_comboboxentry}->set_text_column(0); + $browser->{revision_comboboxentry}->set_wrap_width(2); $browser->{directory_comboboxentry}-> set_model(Gtk2::ListStore->new("Glib::String")); $browser->{directory_comboboxentry}->set_text_column(0); $browser->{directory_comboboxentry}->set_wrap_width(2); - $browser->{revision_comboboxentry}-> - set_model(Gtk2::ListStore->new("Glib::String")); - $browser->{revision_comboboxentry}->set_text_column(0); - $browser->{revision_comboboxentry}->set_wrap_width(2); # Setup the tree view manifest file browser. @@ -1801,6 +1801,15 @@ sub get_browser_window(;$$$$$) $browser->{file_displayed_id} = ""; &{$browser->{update_handler}}($browser, ALL_CHANGED); + # Now the browser instance is completely initialised, set up the + # branch, revision and directory comboboxentry widgets for + # auto-completion. + + activate_auto_completion($browser->{branch_comboboxentry}, $browser); + activate_auto_completion($browser->{revision_comboboxentry}, $browser); + activate_auto_completion($browser->{directory_comboboxentry}, + $browser); + } else {