ext/wxMenuItem.cpp

Summary

Maintainability
Test Coverage
/*
 * wxMenuItem.cpp
 *
 *  Created on: 18.02.2012
 *      Author: hanmac
 */

#include "wxWindow.hpp"
#include "wxApp.hpp"
#include "wxMenu.hpp"
#include "wxMenuItem.hpp"
#include "wxBitmap.hpp"



VALUE rb_cWXMenuItem;

#if wxUSE_MENUS

#define _self unwrap<wxMenuItem*>(self)

namespace RubyWX {
namespace MenuItem {

APP_PROTECT(wxMenuItem)

macro_attr(Menu,wxMenu*)
macro_attr_with_func(Id,wrapID,unwrapID)
macro_attr_enum(Kind,wxItemKind)
macro_attr(SubMenu,wxMenu*)

macro_attr_bitmap_func(Bitmap, WRAP_BITMAP_NULL, wxART_MENU, _self->GetKind() == wxITEM_NORMAL)

#define macro_menuitem_attr_get(name, get, gettool, con) \
DLL_LOCAL VALUE _get##name(VALUE self)\
{ \
    if(con) { \
        wxMenu *menu = _self->GetMenu();\
        int id = _self->GetId();\
        if(menu && menu->FindItem(id)) {\
            return wrap(menu->gettool(id));\
        }\
        return wrap(_self->get());\
    }else {\
        return Qnil;\
    }\
}\



#define macro_menuitem_attr_func(name, type, get, set, gettool, settool, con) \
macro_menuitem_attr_get(name, get, gettool, con) \
DLL_LOCAL VALUE _set##name(VALUE self,VALUE other)\
{\
    rb_check_frozen(self);\
    if(con) { \
        wxMenu *menu = _self->GetMenu();\
        if(menu) {\
            int id = _self->GetId();\
            if(menu->FindItem(id)) {\
                menu->settool(id, unwrap<type>(other));\
                return other;\
            }\
        }\
        _self->set(unwrap<type>(other));\
    }\
    return other;\
}

macro_menuitem_attr_func(Help, wxString, GetHelp, SetHelp, GetHelpString, SetHelpString, true)
macro_menuitem_attr_func(Enabled, bool, IsEnabled, Enable, IsEnabled, Enable, true)
macro_menuitem_attr_func(Checked, bool, IsChecked, Check, IsChecked, Check, _self->GetMenu() && _self->IsCheckable())

macro_menuitem_attr_get(ItemLabel, GetItemLabel, GetLabel, true)

DLL_LOCAL VALUE _setItemLabel(VALUE self,VALUE val)
{
    rb_check_frozen(self);
    wxString cval(unwrap<wxString>(val));

    wxWindowID id = _self->GetId();

    if((!_self->IsSeparator() || !wxIsStockID(id)) && cval.empty()){
        rb_raise(rb_eArgError,"id '%" PRIsVALUE "' (%d) needs an text", RB_OBJ_STRING(_getId(self)), id);
    }

    wxMenu *menu = _self->GetMenu();

    if(menu && menu->FindItem(id)) {
        menu->SetLabel(id, cval);

    } else {
        _self->SetItemLabel(cval);
    }

    return val;
}

DLL_LOCAL VALUE _initialize(int argc,VALUE *argv,VALUE self)
{
    VALUE hash;
    rb_scan_args(argc, argv, "00:",&hash);

    wxMenu *parentMenu = NULL;
    int id = wxID_SEPARATOR;
    wxString text = wxEmptyString;
    wxString help = wxEmptyString;
    wxItemKind kind = wxITEM_NORMAL;
    wxMenu *subMenu = NULL;

    if(!NIL_P(hash))
    {
            set_hash_option(hash,"id",id,unwrapID);
            set_hash_option(hash,"text",text);
            set_hash_option(hash,"help",help);

            set_hash_option(hash,"kind",kind,unwrapenum<wxItemKind>);

            set_hash_option(hash,"help",help);
            set_hash_option(hash,"parent",parentMenu);
            set_hash_option(hash,"sub",subMenu);
    }

    RTYPEDDATA_DATA(self) = wxMenuItemBase::New(parentMenu,id, text, help, kind, subMenu);

    return self;
}

/* Document-method: initialize_copy
 * call-seq:
 *   initialize_copy(orig)
 *
 * Duplicate an object
*/
DLL_LOCAL VALUE _initialize_copy(VALUE self,VALUE other)
{
    _self->SetKind( unwrap<wxMenuItem*>(other)->GetKind() );

    _setId(self,_getId(other));
    VALUE val = _getItemLabel(other);

    if(RSTRING_LEN(rb_String(val)) != 0)
        _setItemLabel(self,val);

    _setSubMenu(self,_getSubMenu(other));
    _setHelp(self,_getHelp(other));
    if(_self->GetKind() == wxITEM_NORMAL)
        _setBitmap(self,_getBitmap(other));
    return self;
}


/*
 * call-seq:
 *   hash -> Fixnum
 *
 * Generates a Fixnum hash value for this object.
 *
 *
 */
DLL_LOCAL VALUE _getHash(VALUE self)
{
    st_index_t h = rb_hash_start(0);

    h = rb_hash_uint(h, RB_NUM2LONG(rb_hash(_getId(self))));
    h = rb_hash_uint(h, _self->GetKind());
    h = rb_hash_uint32(h, rb_str_hash(_getItemLabel(self)));
    h = rb_hash_uint(h, rb_str_hash(_getHelp(self)));
    h = rb_hash_uint(h, RB_NUM2LONG(rb_hash(_getBitmap(self))));

    h = rb_hash_end(h);
    return RB_LONG2FIX(h);
}

struct equal_obj {
    wxMenuItem* self;
    VALUE other;
};

VALUE _equal_block(equal_obj *obj)
{
    wxMenuItem *cother = unwrap<wxMenuItem*>(obj->other);

    if(obj->self->GetId() != cother->GetId())
        return Qfalse;

    if(obj->self->GetKind() != cother->GetKind())
        return Qfalse;

    if(obj->self->GetItemLabel() != cother->GetItemLabel())
        return Qfalse;

    if(obj->self->GetHelp() != cother->GetHelp())
        return Qfalse;

    if(obj->self->IsEnabled() != cother->IsEnabled())
        return Qfalse;
    /*
    if(obj->self->IsCheckable() && cother->IsCheckable())
    {
        if(obj->self->IsChecked() != cother->IsChecked())
            return Qfalse;
    }
    //*/

    return Qtrue;
}

/*
 * call-seq:
 *   == item -> bool
 *
 * compares two menu items.
 *
 *
 */
DLL_LOCAL VALUE _equal(VALUE self, VALUE other)
{
    equal_obj obj;
    obj.self = _self;
    obj.other = other;

    return rb_rescue(
        RUBY_METHOD_FUNC(_equal_block),(VALUE)&obj,
        RUBY_METHOD_FUNC(_equal_rescue),Qnil
    );
}

/*
 * call-seq:
 *   marshal_dump -> Array
 *
 * Provides marshalling support for use by the Marshal library.
 * ===Return value
 * Array
 */
DLL_LOCAL VALUE _marshal_dump(VALUE self)
{
    VALUE result = rb_ary_new();

    rb_ary_push(result,RB_INT2NUM(_self->GetKind()));
    rb_ary_push(result,_getId(self));
    rb_ary_push(result,_getItemLabel(self));
//    rb_ary_push(result,_getSubMenu(self));
    rb_ary_push(result,_getHelp(self));
    rb_ary_push(result,_getBitmap(self));
    return result;
}

/*
 * call-seq:
 *   marshal_load(array) -> nil
 *
 * Provides marshalling support for use by the Marshal library.
 *
 *
 */
DLL_LOCAL VALUE _marshal_load(VALUE self,VALUE data)
{
    data = rb_Array(data);

    _setKind(self,RARRAY_AREF(data,0));

    _setId(self,RARRAY_AREF(data,1));
    VALUE val = RARRAY_AREF(data,2);

    if(RSTRING_LEN(rb_String(val)) != 0)
        _setItemLabel(self,val);


    _setHelp(self,RARRAY_AREF(data,3));

    if(_self->GetKind() == wxITEM_NORMAL)
        _setBitmap(self,RARRAY_AREF(data,4));

    return self;
}


}
}

#endif

/*
 * Document-class: WX::Menu::Item
 *
 * This class represents an Item inside a WX::Menu
*/

/* Document-attr: menu
 * returns the parent menu, this attribute are not copied with inititalize_copy or stored with Marshal
 */
/* Document-attr: label
 * returns the label of the menu item. Type is String
 */
/* Document-attr: id
 * returns the Id of the menu item. Type can be Symbol,if pre- or user defined, or Integer if auto generated.
 */
/* Document-attr: sub_menu
 * returns the sub_menu, currently can be copied with inititalize_copy but not stored with Marshal
 */
/* Document-attr: help
 * returns the help string of the menu item. Type is String
 */
/* Document-attr: bitmap
 * returns the Bitmap
 */

DLL_LOCAL void Init_WXMenuItem(VALUE rb_mWX)
{
#if 0
    rb_cWXMenu = rb_define_class_under(rb_mWX,"Menu",rb_cObject);
#endif

#if wxUSE_MENUS
    using namespace RubyWX::MenuItem;
    //
    rb_cWXMenuItem = rb_define_class_under(rb_cWXMenu,"Item",rb_cObject);
    rb_define_alloc_func(rb_cWXMenuItem,_alloc);

#if 0

    rb_define_attr(rb_cWXMenuItem,"kind",1,1);

    rb_define_attr(rb_cWXMenuItem,"menu",1,1);
    rb_define_attr(rb_cWXMenuItem,"label",1,1);
    rb_define_attr(rb_cWXMenuItem,"id",1,1);

    rb_define_attr(rb_cWXMenuItem,"sub_menu",1,1);

    rb_define_attr(rb_cWXMenuItem,"help",1,1);
    rb_define_attr(rb_cWXMenuItem,"enabled",1,1);
    rb_define_attr(rb_cWXMenuItem,"checked",1,1);

    rb_define_attr(rb_cWXMenuItem,"bitmap",1,1);

#endif

    rb_define_method(rb_cWXMenuItem,"initialize",RUBY_METHOD_FUNC(_initialize),-1);

    rb_define_private_method(rb_cWXMenuItem,"initialize_copy",RUBY_METHOD_FUNC(_initialize_copy),1);

    rb_define_attr_method(rb_cWXMenuItem,"kind",_getKind,_setKind);

    rb_define_attr_method(rb_cWXMenuItem,"menu",_getMenu,_setMenu);
    rb_define_attr_method(rb_cWXMenuItem,"label",_getItemLabel,_setItemLabel);
    rb_define_attr_method(rb_cWXMenuItem,"id",_getId,_setId);

    rb_define_attr_method(rb_cWXMenuItem,"sub_menu",_getSubMenu,_setSubMenu);

    rb_define_attr_method(rb_cWXMenuItem,"help",_getHelp,_setHelp);
    rb_define_attr_method(rb_cWXMenuItem,"enabled",_getEnabled,_setEnabled);
    rb_define_attr_method(rb_cWXMenuItem,"checked",_getChecked,_setChecked);

    rb_define_attr_method(rb_cWXMenuItem,"bitmap",_getBitmap,_setBitmap);

    rb_define_method(rb_cWXMenuItem,"marshal_dump",RUBY_METHOD_FUNC(_marshal_dump),0);
    rb_define_method(rb_cWXMenuItem,"marshal_load",RUBY_METHOD_FUNC(_marshal_load),1);

    rb_define_method(rb_cWXMenuItem,"hash",RUBY_METHOD_FUNC(_getHash),0);

    rb_define_method(rb_cWXMenuItem,"==",RUBY_METHOD_FUNC(_equal),1);
    rb_define_alias(rb_cWXMenuItem,"eql?","==");

    registerInfo<wxMenuItem>(rb_cWXMenuItem);

    registerEnum<wxItemKind>("wxItemKind", Qnil)
        ->add(wxITEM_SEPARATOR, "separator")
        ->add(wxITEM_NORMAL, "normal")
        ->add(wxITEM_CHECK, "check")
        ->add(wxITEM_RADIO, "radio")
        ->add(wxITEM_DROPDOWN, "dropdown");

#endif
}