diff --git a/README.md b/README.md index 8c05e72..4a72faa 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ The SketchUp C API is much more limmited than the ruby api. There is no gui eve # Fully implemented classes * Attribute Dictionary +* Attribute Dictionaries * Color * Component Definition * Definition List @@ -16,7 +17,6 @@ The SketchUp C API is much more limmited than the ruby api. There is no gui eve * Texture # Partially implemented classes -* Attribute Dictionaries * Behavior * Component Instance * Entities diff --git a/ext/attribute_dictionaries.c b/ext/attribute_dictionaries.c index c1b14b4..ef8599a 100644 --- a/ext/attribute_dictionaries.c +++ b/ext/attribute_dictionaries.c @@ -3,13 +3,37 @@ #include #include +struct AttributeDictionaryStringIterationContext +{ + VALUE key; + SUAttributeDictionaryRef dictionary; +}; + +void Sketchup_AttributeDictionaries_Get_By_String_Iterator(SUAttributeDictionaryRef dictionary, struct AttributeDictionaryStringIterationContext* dictionary_struct) +{ + VALUE output; + GETSTRING(SUAttributeDictionaryGetName, dictionary, output); + if (strcmp(StringValuePtr(output), StringValuePtr(dictionary_struct->key)) == 0) + dictionary_struct->dictionary = dictionary; +} + static VALUE Sketchup_AttributeDictionaries_get(VALUE self, VALUE key) { - SUModelRef model = {DATA_PTR(self)}; SUAttributeDictionaryRef dictionary = SU_INVALID; - enum SUResult result = SUModelGetAttributeDictionary(model, StringValuePtr(key), &dictionary); - if (result != SU_ERROR_NONE) - return Qnil; + if (rb_ivar_defined(self, rb_intern("@is_model")) == Qtrue && RTEST(rb_iv_get(self, "@is_model"))) + { + SUModelRef model = {DATA_PTR(self)}; + enum SUResult result = SUModelGetAttributeDictionary(model, StringValuePtr(key), &dictionary); + if (result != SU_ERROR_NONE) + return Qnil; + } + else + { + SUEntityRef entity = {DATA_PTR(self)}; + enum SUResult result = SUEntityGetAttributeDictionary(entity, StringValuePtr(key), &dictionary); + if (result != SU_ERROR_NONE) + return Qnil; + } return Data_Wrap_Struct(rb_path2class(SKETCHUP_ATTRIBUTEDICTIONARY), 0, 0, dictionary.ptr); } @@ -33,6 +57,72 @@ static VALUE Sketchup_AttributeDictionaries_length(VALUE self) return ULL2NUM(count); } +static VALUE Sketchup_AttributeDictionaries_delete(VALUE self, VALUE dictionary) +{ + if (rb_ivar_defined(self, rb_intern("@is_model")) == Qtrue && RTEST(rb_iv_get(self, "@is_model"))) + { + SUModelRef model = {DATA_PTR(self)}; + if (rb_type(dictionary) == T_STRING) + { + struct AttributeDictionaryStringIterationContext dictionary_struct = {dictionary, SU_INVALID}; + FOREACH(SUModelGetNumAttributeDictionaries, SUModelGetAttributeDictionaries, SUAttributeDictionaryRef, model, Sketchup_AttributeDictionaries_Get_By_String_Iterator, &dictionary_struct); + if (SUIsInvalid(dictionary_struct.dictionary)) + return Qnil; + SUAttributeDictionaryRelease(&dictionary_struct.dictionary); + size_t ad_count = 0; + size_t ad_len = 0; + SUModelGetNumAttributeDictionaries(model, &ad_len); + SUAttributeDictionaryRef* dictionaries; + SUModelGetAttributeDictionaries(model, ad_len, dictionaries, &ad_count); + return Data_Wrap_Struct(rb_path2class(SKETCHUP_ATTRIBUTEDICTIONARIES), 0, 0, dictionaries); + } + else if (rb_obj_is_kind_of(dictionary, rb_path2class(SKETCHUP_ATTRIBUTEDICTIONARY))) + { + SUAttributeDictionaryRef dictionary_ref = {DATA_PTR(dictionary)}; + SUAttributeDictionaryRelease(&dictionary_ref); + size_t ad_count = 0; + size_t ad_len = 0; + SUModelGetNumAttributeDictionaries(model, &ad_len); + SUAttributeDictionaryRef* dictionaries; + SUModelGetAttributeDictionaries(model, ad_len, dictionaries, &ad_count); + return Data_Wrap_Struct(rb_path2class(SKETCHUP_ATTRIBUTEDICTIONARIES), 0, 0, dictionaries); + } + else + rb_raise(rb_eArgError, "Wrong argument type. Expected String or AttributeDictionary"); + } + else + { + SUEntityRef entity = {DATA_PTR(self)}; + if (rb_type(dictionary) == T_STRING) + { + struct AttributeDictionaryStringIterationContext dictionary_struct = {dictionary, SU_INVALID}; + FOREACH(SUEntityGetNumAttributeDictionaries, SUEntityGetAttributeDictionaries, SUAttributeDictionaryRef, entity, Sketchup_AttributeDictionaries_Get_By_String_Iterator, &dictionary_struct); + if (SUIsInvalid(dictionary_struct.dictionary)) + return Qnil; + SUAttributeDictionaryRelease(&dictionary_struct.dictionary); + size_t ad_count = 0; + size_t ad_len = 0; + SUEntityGetNumAttributeDictionaries(entity, &ad_len); + SUAttributeDictionaryRef* dictionaries; + SUEntityGetAttributeDictionaries(entity, ad_len, dictionaries, &ad_count); + return Data_Wrap_Struct(rb_path2class(SKETCHUP_ATTRIBUTEDICTIONARIES), 0, 0, dictionaries); + } + else if (rb_obj_is_kind_of(dictionary, rb_path2class(SKETCHUP_ATTRIBUTEDICTIONARY))) + { + SUAttributeDictionaryRef dictionary_ref = {DATA_PTR(self)}; + SUAttributeDictionaryRelease(&dictionary_ref); + size_t ad_count = 0; + size_t ad_len = 0; + SUEntityGetNumAttributeDictionaries(entity, &ad_len); + SUAttributeDictionaryRef* dictionaries; + SUEntityGetAttributeDictionaries(entity, ad_len, dictionaries, &ad_count); + return Data_Wrap_Struct(rb_path2class(SKETCHUP_ATTRIBUTEDICTIONARIES), 0, 0, dictionaries); + } + else + rb_raise(rb_eArgError, "Wrong argument type. Expected String or AttributeDictionary"); + } +} + VALUE AttributeDictionaries_Init(VALUE Sketchup, VALUE Sketchup_Entity) { VALUE Sketchup_AttributeDictionaries = rb_define_class_under(Sketchup, ATTRIBUTEDICTIONARIES, Sketchup_Entity); @@ -42,5 +132,6 @@ VALUE AttributeDictionaries_Init(VALUE Sketchup, VALUE Sketchup_Entity) rb_define_method(Sketchup_AttributeDictionaries, "each", Sketchup_AttributeDictionaries_each, 0); rb_define_method(Sketchup_AttributeDictionaries, "length", Sketchup_AttributeDictionaries_length, 0); rb_define_method(Sketchup_AttributeDictionaries, "size", Sketchup_AttributeDictionaries_length, 0); + rb_define_method(Sketchup_AttributeDictionaries, "delete", Sketchup_AttributeDictionaries_delete, 1); return Sketchup_AttributeDictionaries; } \ No newline at end of file diff --git a/ext/model.c b/ext/model.c index 21c5010..164ff06 100644 --- a/ext/model.c +++ b/ext/model.c @@ -26,7 +26,9 @@ static VALUE Sketchup_Model_definitions(VALUE self) static VALUE Sketchup_Model_attribute_dictionaries(VALUE self) { - return Data_Wrap_Struct(rb_path2class(SKETCHUP_ATTRIBUTEDICTIONARIES), 0, 0, DATA_PTR(self)); + VALUE obj = Data_Wrap_Struct(rb_path2class(SKETCHUP_ATTRIBUTEDICTIONARIES), 0, 0, DATA_PTR(self)); + rb_iv_set(obj, "@is_model", Qtrue); + return obj; } VALUE Model_Init(VALUE Sketchup, VALUE rb_cObject) diff --git a/test/test_attribute_dictionaries.rb b/test/test_attribute_dictionaries.rb index ff143cb..0d2522e 100644 --- a/test/test_attribute_dictionaries.rb +++ b/test/test_attribute_dictionaries.rb @@ -14,17 +14,26 @@ def test_object end def test_accessor - skip assert_instance_of(Sketchup::AttributeDictionary, @attribute_dictionaries['GeoReference']) - assert_instance_of(Sketchup::AttributeDictionary, @attribute_dictionaries[@attribute_dictionaries['GeoReference']]) + entity = Sketchup.active_model.definitions.find { |d| d.name == 'Heather' } + entity.attribute_dictionary('Age', 42) + assert_instance_of(Sketchup::AttributeDictionary, entity.attribute_dictionaries['Age']) end def test_count assert_equal(3, @attribute_dictionaries.count) end - def test_delete - skip + def test_delete_by_dictionary + assert_equal(3, @attribute_dictionaries.length) + @attribute_dictionaries.delete(@attribute_dictionaries['GeoReference']) + assert_equal(2, @attribute_dictionaries.length) + end + + def test_delete_by_name + assert_equal(3, @attribute_dictionaries.length) + @attribute_dictionaries.delete('GeoReference') + assert_equal(2, @attribute_dictionaries.length) end def test_each @@ -40,6 +49,10 @@ def test_length assert_equal(3, @attribute_dictionaries.length) end + def test_count + assert_equal(3, @attribute_dictionaries.count) + end + def test_size assert_equal(3, @attribute_dictionaries.size) end