[前][次][番号順一覧][スレッド一覧]

ruby-changes:6709

From: suke <ko1@a...>
Date: Sat, 26 Jul 2008 21:31:44 +0900 (JST)
Subject: [ruby-changes:6709] Ruby:r18225 (trunk): * ext/win32ole/win32ole.c (Init_win32ole): add

suke	2008-07-26 21:27:57 +0900 (Sat, 26 Jul 2008)

  New Revision: 18225

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=18225

  Log:
    * ext/win32ole/win32ole.c (Init_win32ole): add
      WIN32OLE_EVENT#handler=, WIN32OLE_EVENT#handler
    
    * test/win32ole/test_win32ole_event.rb: ditto.

  Modified files:
    trunk/ChangeLog
    trunk/ext/win32ole/win32ole.c
    trunk/test/win32ole/test_win32ole_event.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 18224)
+++ ChangeLog	(revision 18225)
@@ -1,3 +1,10 @@
+Sat Jul 26 21:17:18 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* ext/win32ole/win32ole.c (Init_win32ole): add
+	  WIN32OLE_EVENT#handler=, WIN32OLE_EVENT#handler
+
+	* test/win32ole/test_win32ole_event.rb: ditto.
+
 Sat Jul 26 07:44:14 2008  Masaki Suketa  <masaki.suketa@n...>
 
 	* ext/win32ole/win32ole.c (add_event_call_back): remove unused 
Index: ext/win32ole/win32ole.c
===================================================================
--- ext/win32ole/win32ole.c	(revision 18224)
+++ ext/win32ole/win32ole.c	(revision 18225)
@@ -118,7 +118,7 @@
 
 #define WC2VSTR(x) ole_wc2vstr((x), TRUE)
 
-#define WIN32OLE_VERSION "1.2.9"
+#define WIN32OLE_VERSION "1.3.0"
 
 typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
     (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
@@ -499,6 +499,7 @@
 static VALUE foleparam_inspect(VALUE self);
 static long ole_search_event_at(VALUE ary, VALUE ev);
 static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL  *is_default);
+static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler);
 static void ole_delete_event(VALUE ary, VALUE ev);
 static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
 static VALUE hash2result(VALUE hash);
@@ -520,6 +521,8 @@
 static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self);
 static VALUE fev_off_event(int argc, VALUE *argv, VALUE self);
 static VALUE fev_unadvise(VALUE self);
+static VALUE fev_set_handler(VALUE self, VALUE val);
+static VALUE fev_get_handler(VALUE self);
 static VALUE evs_push(VALUE ev);
 static VALUE evs_delete(long i);
 static VALUE evs_entry(long i);
@@ -7434,7 +7437,24 @@
     }
     return def_event;
 }
+static VALUE
+ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler)
+{
+    VALUE mid;
 
+    *is_default_handler = FALSE;
+    mid = rb_to_id(rb_sprintf("on%s", StringValuePtr(ev)));
+    if (rb_respond_to(handler, mid)) {
+	return mid;
+    }
+    mid = rb_intern("method_missing");
+    if (rb_respond_to(handler, mid)) {
+	*is_default_handler = TRUE;
+	return mid;
+    }
+    return Qnil;
+}
+
 static void
 ole_delete_event(VALUE ary, VALUE ev)
 {
@@ -7502,8 +7522,9 @@
 {
     VALUE *parg = (VALUE *)arg;
     VALUE handler = parg[0];
-    VALUE args = parg[1];
-    return rb_apply(handler, rb_intern("call"), args);
+    VALUE mid = parg[1];
+    VALUE args = parg[2];
+    return rb_apply(handler, mid, args);
 }
 
 static VALUE
@@ -7540,9 +7561,11 @@
     unsigned int i;
     ITypeInfo *pTypeInfo;
     VARIANT *pvar;
-    VALUE ary, obj, event, handler, args, outargv, ev, result;
-    VALUE arg[2];
-    VALUE is_outarg;
+    VALUE ary, obj, event, args, outargv, ev, result;
+    VALUE handler = Qnil;
+    VALUE arg[3];
+    VALUE mid;
+    VALUE is_outarg = Qfalse;
     BOOL is_default_handler = FALSE;
     int state;
 
@@ -7564,9 +7587,21 @@
     }
     ev = WC2VSTR(bstr);
     event = ole_search_event(ary, ev, &is_default_handler);
-    if (NIL_P(event)) {
-        return NOERROR;
+    if (TYPE(event) == T_ARRAY) {
+	handler = rb_ary_entry(event, 0);
+	mid = rb_intern("call");
+	is_outarg = rb_ary_entry(event, 3);
+    } else {
+	handler = rb_ivar_get(obj, rb_intern("handler"));
+	if (handler == Qnil) {
+	    return NOERROR;
+	}
+	mid = ole_search_handler_method(handler, ev, &is_default_handler);
     }
+    if (handler == Qnil || mid == Qnil) {
+	return NOERROR;
+    }
+
     args = rb_ary_new();
     if (is_default_handler) {
         rb_ary_push(args, ev);
@@ -7577,8 +7612,6 @@
         pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
         rb_ary_push(args, ole_variant2val(pvar));
     }
-    handler = rb_ary_entry(event, 0);
-    is_outarg = rb_ary_entry(event, 3);
     outargv = Qnil;
     if (is_outarg == Qtrue) {
 	outargv = rb_ary_new();
@@ -7593,7 +7626,8 @@
      * and exit ruby process by Win32OLE itself.
      */
     arg[0] = handler;
-    arg[1] = args;
+    arg[1] = mid;
+    arg[2] = args;
     result = rb_protect(exec_callback, (VALUE)arg, &state);
     if (state != 0) {
 	rescue_callback(Qnil);
@@ -8260,6 +8294,64 @@
     return rb_funcall(ary_ole_event, rb_intern("length"), 0);
 }
 
+/*
+ *  call-seq:
+ *     WIN32OLE_EVENT#handler=
+ *
+ *  sets event handler object. If handler object has onXXX
+ *  method according to XXX event, then onXXX method is called 
+ *  when XXX event occurs.
+ *  
+ *  If handler object has method_missing and there is no
+ *  method according to the event, then method_missing
+ *  called and 1-st argument is event name.
+ *
+ *  If handler object has onXXX method and there is block
+ *  defined by WIN32OLE_EVENT#on_event('XXX'){},
+ *  then block is executed but handler object method is not called
+ *  when XXX event occurs.
+ *
+ *      class Handler
+ *        def onStatusTextChange(text)
+ *          puts "StatusTextChanged"
+ *        end
+ *        def onPropertyChange(prop)
+ *          puts "PropertyChanged"
+ *        end
+ *        def method_missing(ev, *arg)
+ *          puts "other event #{ev}"
+ *        end
+ *      end
+ *      
+ *      handler = Handler.new
+ *      ie = WIN32OLE.new('InternetExplorer.Application')
+ *      ev = WIN32OLE_EVENT.new(ie)
+ *      ev.on_event("StatusTextChange") {|*args|
+ *        puts "this block executed."
+ *        puts "handler.onStatusTextChange method is not called."
+ *      }
+ *      ev.handler = handler
+ *
+ */
+static VALUE
+fev_set_handler(VALUE self, VALUE val)
+{
+    return rb_ivar_set(self, rb_intern("handler"), val);
+}
+
+/*
+ *  call-seq:
+ *     WIN32OLE_EVENT#handler
+ *
+ *  returns handler object. 
+ *  
+ */
+static VALUE
+fev_get_handler(VALUE self)
+{
+    return rb_ivar_get(self, rb_intern("handler"));
+}
+
 static void 
 olevariant_free(struct olevariantdata *pvar)
 {
@@ -8896,6 +8988,8 @@
     rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1);
     rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1);
     rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0);
+    rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1);
+    rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0);
 
     cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
     rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
Index: test/win32ole/test_win32ole_event.rb
===================================================================
--- test/win32ole/test_win32ole_event.rb	(revision 18224)
+++ test/win32ole/test_win32ole_event.rb	(revision 18225)
@@ -6,6 +6,8 @@
 
 if defined?(WIN32OLE_EVENT)
   class TestWIN32OLE_EVENT < Test::Unit::TestCase
+    module IE
+    end
     def create_temp_html
       fso = WIN32OLE.new('Scripting.FileSystemObject')
       dummy_file = fso.GetTempName + ".html"
@@ -22,10 +24,18 @@
       sleep 0.1
     end
 
+    def wait_ie
+      while @ie.readyState != IE::READYSTATE_COMPLETE
+        message_loop
+      end
+    end
+
     def setup
       WIN32OLE_EVENT.message_loop
       @ie = WIN32OLE.new("InternetExplorer.Application")
-      message_loop
+      if !defined?(IE::READYSTATE_COMPLETE)
+        WIN32OLE.const_load(@ie, IE)
+      end
       @ie.visible = true
       message_loop
       @event = ""
@@ -61,11 +71,7 @@
       ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
       ev.on_event {|*args| default_handler(*args)}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents') 
-        GC.start  
-        message_loop
-      end
+      wait_ie
       assert_match(/BeforeNavigate/, @event)
       assert_match(/NavigateComplete/, @event)
     end
@@ -75,9 +81,7 @@
       ev.on_event('BeforeNavigate') {|*args| handler1}
       ev.on_event('BeforeNavigate') {|*args| handler2}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_equal("handler2", @event2)
     end
 
@@ -86,9 +90,7 @@
       ev.on_event {|*args| handler1}
       ev.on_event {|*args| handler2}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_equal("handler2", @event2)
     end
 
@@ -98,9 +100,7 @@
       ev.on_event{|*args| handler2}
       ev.on_event('NavigateComplete'){|*args| handler3(*args)}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert(@event3!="")
       assert("handler2", @event2)
     end
@@ -110,9 +110,7 @@
       ev.on_event {|*args| default_handler(*args)}
       ev.on_event('NavigateComplete'){|*args| handler3(*args)}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_match(/BeforeNavigate/, @event)
       assert(/NavigateComplete/ !~ @event)
       assert(@event!="")
@@ -122,16 +120,12 @@
       ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
       ev.on_event {|*args| default_handler(*args)}
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_match(/BeforeNavigate/, @event)
       ev.unadvise
       @event = ""
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_equal("", @event);
       assert_raise(WIN32OLERuntimeError) {
         ev.on_event {|*args| default_handler(*args)}
@@ -158,9 +152,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
 
@@ -171,9 +163,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
 
@@ -184,9 +174,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
 
@@ -197,9 +185,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
     
@@ -210,9 +196,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
 
@@ -223,9 +207,7 @@
       }
       bl = @ie.locationURL
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
+      wait_ie
       assert_equal(bl, @ie.locationURL)
     end
 
@@ -234,10 +216,7 @@
       ev.on_event{handler1}
       ev.off_event
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
-      WIN32OLE_EVENT.message_loop
+      wait_ie
       assert_equal("", @event2)
     end
 
@@ -246,10 +225,7 @@
       ev.on_event('BeforeNavigate2'){handler1}
       ev.off_event('BeforeNavigate2')
       @ie.navigate("file:///#{@f}")
-      while @ie.busy
-        message_loop
-      end
-      WIN32OLE_EVENT.message_loop
+      wait_ie
       assert_equal("", @event2)
     end
 
@@ -267,6 +243,7 @@
 
     def teardown
       @ie.quit
+      message_loop
       @ie = nil
       i = 0
       begin 
@@ -280,5 +257,58 @@
       GC.start
       message_loop
     end
+
+    class Handler1
+      attr_reader :val1, :val2, :val3, :val4
+      def initialize
+        @val1 = nil
+        @val2 = nil
+        @val3 = nil
+        @val4 = nil
+      end
+      def onStatusTextChange(t)
+        @val1 = t
+      end
+      def onProgressChange(p, pmax)
+        @val2 = p
+        @val3 = pmax
+      end
+      def onPropertyChange(p)
+        @val4 = p
+      end
+    end
+
+    class Handler2
+      attr_reader :ev
+      def initialize
+        @ev = ""
+      end
+      def method_missing(ev, *arg)
+        @ev += ev
+      end
+    end
+
+    def test_handler1
+      ev = WIN32OLE_EVENT.new(@ie)
+      h1 = Handler1.new
+      ev.handler = h1
+      @ie.navigate("file:///#{@f}")
+      wait_ie
+      assert(h1.val1)
+      assert_equal(h1.val1, ev.handler.val1)
+      assert(h1.val2)
+      assert(h1.val3)
+      assert(h1.val4)
+    end
+
+    def test_handler2
+      ev = WIN32OLE_EVENT.new(@ie)
+      h2 = Handler2.new
+      ev.handler = h2
+      @ie.navigate("file:///#{@f}")
+      wait_ie
+      assert(h2.ev != "")
+    end
+
   end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]