[Kazehakase-cvs] CVS update: kazehakase/data/ext/ruby/kz

Zurück zum Archiv-Index

Kouhei Sutou kous****@users*****
Thu May 11 17:21:26 JST 2006


Index: kazehakase/data/ext/ruby/kz/Makefile.am
diff -u kazehakase/data/ext/ruby/kz/Makefile.am:1.2 kazehakase/data/ext/ruby/kz/Makefile.am:1.3
--- kazehakase/data/ext/ruby/kz/Makefile.am:1.2	Wed May 10 17:43:19 2006
+++ kazehakase/data/ext/ruby/kz/Makefile.am	Thu May 11 17:21:26 2006
@@ -6,6 +6,8 @@
 extruby_DATA = \
 	ruby-dialog.rb \
 	ruby-completion.rb \
+	search-window.rb \
+	utils.rb \
 	actions.rb
 
 EXTRA_DIST = \
Index: kazehakase/data/ext/ruby/kz/ruby-dialog.rb
diff -u kazehakase/data/ext/ruby/kz/ruby-dialog.rb:1.11 kazehakase/data/ext/ruby/kz/ruby-dialog.rb:1.12
--- kazehakase/data/ext/ruby/kz/ruby-dialog.rb:1.11	Thu May 11 13:31:47 2006
+++ kazehakase/data/ext/ruby/kz/ruby-dialog.rb	Thu May 11 17:21:26 2006
@@ -17,6 +17,7 @@
 #
 
 require "kz/ruby-completion"
+require "kz/search-window"
 
 module Kz
   class SandBox
@@ -67,6 +68,7 @@
         false
       end
       init_history
+      init_search
       init_output_area
       init_input_area
       init_buttons
@@ -99,6 +101,44 @@
       end
     end
 
+    def init_search
+      searcher = Object.new
+      def searcher.regexp(text)
+        /#{Regexp.quote(text)}/i
+      end
+      @search_window = SearchWindow.new(searcher)
+      @search_window.window.set_transient_for(@dialog)
+      entry = @search_window.entry
+      direction = @search_window.direction
+      entry.signal_connect("key_press_event") do |widget, event|
+        handled = false
+        if event.state.control_mask?
+          handled = true
+          case event.keyval
+          when Gdk::Keyval::GDK_s
+            search_history(true)
+          when Gdk::Keyval::GDK_r
+            search_history(false)
+          when Gdk::Keyval::GDK_g
+            stop_history_search
+          else
+            handled = false
+          end
+        end
+        handled
+      end
+      entry.signal_connect("changed") do
+        search_history_with_current_input
+      end
+      direction.signal_connect("toggled") do
+        search_history_with_current_input(true)
+      end
+      entry.signal_connect("activate") do
+        stop_history_search
+        true
+      end
+    end
+
     def init_output_area
       init_text_view
     end
@@ -115,7 +155,7 @@
         @buffer.apply_tag(@all_tag, start, iter)
         false
       end
-      sw = add_scrooled_window(@view)
+      sw = add_scrolled_window(@view)
       @dialog.vbox.pack_start(sw, true, true, 0)
     end
 
@@ -235,13 +275,25 @@
         handled = true
       when Gdk::Keyval::GDK_i
         @ruby_exp_completion.insert_prefix if event.state.control_mask?
+      when Gdk::Keyval::GDK_s
+        if event.state.control_mask?
+          search_history(true)
+          handled = true
+        end
+      when Gdk::Keyval::GDK_r
+        if event.state.control_mask?
+          search_history(false)
+          handled = true
+        end
       end
       handled
     end
 
     def activate_input
       text =****@entry*****
-      unless text.empty?
+      if text.empty?
+        @history_spin.value = @@history.size
+      else
         eval_print(text)
         update_history(text)
       end
@@ -280,6 +332,61 @@
       handled
     end
 
+    def search_history(forward=false)
+      unless @search_window.visible?
+        @search_window.show
+        adjust_search_window
+      end
+
+      if @search_window.forward? == forward
+        search_history_with_current_input(true)
+      else
+        @search_window.forward = forward
+      end
+    end
+
+    def stop_history_search
+      @search_window.hide
+      @search_window.entry.text = ""
+    end
+
+    def adjust_search_window
+      Utils.move_to_bottom_left_outer(@entry, @search_window.window)
+    end
+
+    def search_history_with_current_input(search_next=false)
+      Kz.barrier do
+        return if @search_window.empty?
+        change_to_matched_history(@search_window.regexp,
+                                  @search_window.forward?,
+                                  search_next)
+      end
+    end
+
+    def change_to_matched_history(reg, forward, search_next=false)
+      current_index = @history_spin.value.to_i
+      indexes = []
+      @@history.each_with_index do |text, i|
+        indexes << i if reg =~ text
+      end
+      target_index = nil
+      indexes.each_with_index do |index, i|
+        if index == current_index
+          target_index = i
+          target_index += (forward ? 1 : -1) if search_next
+          break
+        elsif index > current_index
+          target_index = i + (forward ? 0 : -1)
+          break
+        end
+      end
+      target_index = indexes.size - 1 if target_index.nil? and !forward
+      if target_index and target_index >= 0 and target_index < indexes.size
+        @history_spin.value = indexes[target_index].to_f
+        @entry.position = reg =~ @entry.text
+      end
+    end
+
     def eval_print(text)
       @buffer.insert(@buffer.end_iter, ">> ")
       @buffer.insert(@buffer.end_iter, text, @input_tag)
@@ -293,7 +400,7 @@
       @view.scroll_to_mark(@end_mark, 0, false, 0, 1)
     end
 
-    def add_scrooled_window(widget)
+    def add_scrolled_window(widget)
       sw = Gtk::ScrolledWindow.new
       sw.border_width = 5
       sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
Index: kazehakase/data/ext/ruby/kz/search-window.rb
diff -u /dev/null kazehakase/data/ext/ruby/kz/search-window.rb:1.1
--- /dev/null	Thu May 11 17:21:26 2006
+++ kazehakase/data/ext/ruby/kz/search-window.rb	Thu May 11 17:21:26 2006
@@ -0,0 +1,103 @@
+module Kz
+  class SearchWindow
+
+    attr_reader :window, :direction, :entry
+    def initialize(searcher)
+      @searcher = searcher
+      init_window
+    end
+
+    def show
+      send_focus_change(true)
+      @window.show
+    end
+
+    def hide
+      send_focus_change(false)
+      @window.hide
+    end
+
+    def visible?
+      @window.visible?
+    end
+
+    def destroy
+      hide
+      @window.destroy
+    end
+
+    def forward=(forward)
+      @direction.active = forward
+    end
+
+    def forward?
+      @direction.active?
+    end
+
+    def empty?
+      /\A\s*\z/ =~ @entry.text
+    end
+
+    def regexp
+      @searcher.regexp(@entry.text)
+    end
+
+    private
+    def init_window
+      @window = Gtk::Window.new(Gtk::Window::POPUP)
+      @window.modal = true
+      init_frame
+      init_box
+      init_entry
+      init_direction
+    end
+
+    def init_frame
+      @frame = Gtk::Frame.new
+      @frame.shadow_type = Gtk::ShadowType::ETCHED_IN
+      @frame.show
+      @window.add(@frame)
+    end
+
+    def init_box
+      @box = Gtk::HBox.new
+      @box.border_width = 3
+      @box.show
+      @frame.add(@box)
+    end
+
+    def init_entry
+      @entry = Gtk::Entry.new
+      @entry.show
+      @box.add(@entry)
+    end
+
+    def init_direction
+      @direction = Gtk::ToggleButton.new
+      @arrow = Gtk::Arrow.new(Gtk::Arrow::LEFT, Gtk::SHADOW_NONE)
+      @arrow.show
+      @direction.add(@arrow)
+      @direction.can_focus = false
+      @direction.show
+      @box.add(@direction)
+      @direction.signal_connect("toggled") do |button|
+        if forward?
+          type = Gtk::Arrow::RIGHT
+        else
+          type = Gtk::Arrow::LEFT
+        end
+        @arrow.set(type, Gtk::SHADOW_NONE)
+      end
+      @direction.active = true
+    end
+
+    def send_focus_change(focus_in)
+      @entry.has_focus = focus_in
+      event = Gdk::EventFocus.new(Gdk::EventFocus::FOCUS_CHANGE)
+      event.window =****@entry*****
+      event.in = focus_in
+      @entry.event(event)
+      @entry.notify("has-focus")
+    end
+  end
+end
Index: kazehakase/data/ext/ruby/kz/utils.rb
diff -u /dev/null kazehakase/data/ext/ruby/kz/utils.rb:1.1
--- /dev/null	Thu May 11 17:21:26 2006
+++ kazehakase/data/ext/ruby/kz/utils.rb	Thu May 11 17:21:26 2006
@@ -0,0 +1,89 @@
+module Kz
+  module Utils
+    module_function
+    def move_to(base, target)
+      window = base.window
+      screen = window.screen
+      num = screen.get_monitor(window)
+      monitor = screen.monitor_geometry(num)
+      window_x, window_y = window.origin
+      window_width, window_height = window.size
+      target_width, target_height = target.size_request
+
+      args = [window_x, window_y, window_width, window_height]
+      args.concat([target_width, target_height])
+      args.concat([screen.width, screen.height])
+      x, y = yield(*args)
+
+      target.move(x, y)
+    end
+
+    def compute_left_x(base_x)
+      [base_x, 0].max
+    end
+
+    def compute_right_x(base_x, base_width, target_width, max_x)
+      right = base_x + base_width - target_width
+      [[right, max_x - target_width].min, 0].max
+    end
+
+    def compute_top_y(base_y)
+      [base_y, 0].max
+    end
+
+    def compute_bottom_y(base_y, base_height, target_height, max_y)
+      bottom = base_y + base_height - target_height
+      [[bottom, max_y - target_height].min, 0].max
+    end
+
+    def move_to_top_left(base, target)
+      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
+        [compute_left_x(bx), compute_top_y(by)]
+      end
+    end
+
+    def move_to_top_left_outer(base, target)
+      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
+        [compute_left_x(bx), compute_top_y(by) - th]
+      end
+    end
+
+    def move_to_top_right(base, target)
+      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
+        [compute_right_x(bx, bw, tw, sw), compute_top_y(by)]
+      end
+    end
+
+    def move_to_top_right_outer(base, target)
+      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
+        [compute_right_x(bx, bw, tw, sw), compute_top_y(by) - th]
+      end
+    end
+
+    def move_to_bottom_left(base, target)
+      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
+        [compute_left_x(bx), compute_bottom_y(by, bh, th, sh)]
+      end
+    end
+
+    def move_to_bottom_left_outer(base, target)
+      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
+        [compute_left_x(bx), compute_bottom_y(by, bh, th, sh) + th]
+      end
+    end
+
+    def move_to_bottom_right(base, target)
+      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
+        [compute_right_x(bx, bw, tw, sw),
+         compute_bottom_y(by, bh, th, sh)]
+      end
+    end
+
+    def move_to_bottom_right(base, target)
+      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
+        [compute_right_x(bx, bw, tw, sw),
+         compute_bottom_y(by, bh, th, sh) + th]
+      end
+    end
+  end
+end


More information about the Kazehakase-cvs mailing list
Zurück zum Archiv-Index