ext/wxSizer.cpp

Summary

Maintainability
Test Coverage
/*
 * wxSizer.cpp
 *
 *  Created on: 20.03.2012
 *      Author: hanmac
 */
#include "wxSizer.hpp"
#include "wxSizerItem.hpp"
#include "wxWindow.hpp"
#include "wxPoint.hpp"

#define _self unwrap<wxSizer*>(self)

VALUE rb_cWXSizer;

template <>
wxSizerFlags unwrap< wxSizerFlags >(const VALUE &hash)
{
    wxSizerFlags result;
    if(!rb_obj_is_kind_of(hash,rb_cHash))
        return result;
    VALUE val;

    set_obj_option(hash, "expand", &wxSizerFlags::Expand, result);
    set_obj_option(hash, "shaped", &wxSizerFlags::Shaped, result);
    set_obj_option(hash, "border", &wxSizerFlags::Border, result);
    set_obj_option(hash, "proportion", &wxSizerFlags::Proportion, result);

    if(!NIL_P(val=rb_hash_aref(hash,RB_ID2SYM(rb_intern("align")))))
    {
        if(RB_SYMBOL_P(val))
        {
            if(RB_SYM2ID(val) == rb_intern("left"))
                result.Left();
            if(RB_SYM2ID(val) == rb_intern("right"))
                result.Right();
            if(RB_SYM2ID(val) == rb_intern("bottom"))
                result.Bottom();
            if(RB_SYM2ID(val) == rb_intern("top"))
                result.Top();
            if(RB_SYM2ID(val) == rb_intern("center"))
                result.Center();
#ifdef HAVE_CONST_WXALIGN_CENTER_VERTICAL
#ifdef HAVE_WXSIZERFLAGS_CENTERVERTICAL
            if(RB_SYM2ID(val) == rb_intern("center_vertical"))
                result.CenterVertical();
            if(RB_SYM2ID(val) == rb_intern("center_horizontal"))
                result.CenterHorizontal();
#else
            if(RB_SYM2ID(val) == rb_intern("center_vertical"))
                result.Align(wxALIGN_CENTER_VERTICAL);
            if(RB_SYM2ID(val) == rb_intern("center_horizontal"))
                result.Align(wxALIGN_CENTER_HORIZONTAL);
#endif
#endif
        }
    }

    return result;
}


template <>
wxSizer* unwrap<wxSizer*>(const VALUE &arg)
{
    return unwrapTypedPtr<wxSizer>(arg,rb_cWXSizer);
}


namespace RubyWX {
namespace Sizer {

macro_attr(MinSize,wxSize)
singlereturn(GetSize)
singlereturn(GetPosition)

singlefunc(Layout)


DLL_LOCAL VALUE _initialize(int argc,VALUE *argv,VALUE self)
{
    VALUE args;
    rb_scan_args(argc, argv, "*",&args);
    //rb_call_super(argc,argv);
    if(rb_block_given_p())
        rb_yield(self);
    return self;
}

bool check_window(wxSizer *sizer, wxWindow *window, VALUE hash)
{
    wxSizer *contain = window->GetContainingSizer();
    if(contain)
    {
        VALUE tmp(Qfalse);
        set_hash_option(hash, "reparent", tmp);
        if(tmp) {
            contain->Detach(window);
        }else if(sizer != contain) {
            rb_raise(rb_eArgError, "Adding a window already in a sizer, detach it first!");
        } else {
            rb_raise(rb_eArgError, "Adding a window to the same sizer twice?");
        }
        return false;
    }
    return true;
}

/*
 * call-seq:
 *   add(window, [options])
 *   add(sizer, [options])
 *   add(size, [options])
 *
 * adds a new WX::Sizer::Item
 * ===Arguments
 * * window is a WX::Window
 * * sizer is a WX::Sizer
 * * size is a WX::Size
 *
 * *options: Hash with possible options to set:
 *   * expand true/false says if the element should expand to the whole size
 *   * proportion Integer
 * ===Return value
 * WX::Sizer::Item
 */
DLL_LOCAL VALUE _add(int argc,VALUE *argv,VALUE self)
{
    VALUE obj,hash;
    rb_scan_args(argc, argv, "1:",&obj,&hash);

    wxSizerFlags flags(unwrap<wxSizerFlags>(hash));
    if(rb_obj_is_kind_of(obj, rb_cWXWindow))
    {
        wxWindow *win = unwrap<wxWindow*>(obj);
        if(check_window(_self, win, hash))
            return wrap(_self->Add(win,flags));
    }else if(rb_obj_is_kind_of(obj, rb_cWXSizer))
    {
        return wrap(_self->Add(unwrap<wxSizer*>(obj),flags));
    }else {
        const wxSize &size = unwrap<wxSize>(obj);
        return wrap(_self->Add(size.GetWidth(),size.GetHeight(),flags));
    }
    return Qnil;
}


/*
 * call-seq:
 *   add_spacer(size)
 *
 * adds a new spacer WX::Sizer::Item
 * ===Arguments
 * * size is a Integer
 * ===Return value
 * WX::Sizer::Item
 */
DLL_LOCAL VALUE _add_spacer(VALUE self,VALUE size)
{
    return wrap(_self->AddSpacer(RB_NUM2INT(size)));
}

/*
 * call-seq:
 *   add_stretch_spacer([prop])
 *
 * adds a new stretch spacer WX::Sizer::Item
 * ===Arguments
 * * prop is a Integer
 * ===Return value
 * WX::Sizer::Item
 */
DLL_LOCAL VALUE _add_stretch_spacer(int argc,VALUE *argv,VALUE self)
{
    VALUE prop;
    rb_scan_args(argc, argv, "01",&prop);

    return wrap(_self->AddStretchSpacer(NIL_P(prop) ? 1 : RB_NUM2INT(prop)));
}


/*
 * call-seq:
 *   insert(pos, window, [options])
 *   insert(pos, sizer, [options])
 *   insert(pos, size, [options])
 *
 * inserts a new WX::Sizer::Item into the given position.
 * ===Arguments
 * * pos is Integer
 * * window is a WX::Window
 * * sizer is a WX::Sizer
 * * size is a WX::Size
 *
 * *options: Hash with possible options to set:
 *   * expand true/false says if the element should expand to the whole size
 *   * proportion Integer
 * ===Return value
 * WX::Sizer::Item
 */
DLL_LOCAL VALUE _insert(int argc,VALUE *argv,VALUE self)
{
    VALUE index,obj,hash;
    rb_scan_args(argc, argv, "2:",&index,&obj,&hash);

    wxSizerFlags flags(unwrap<wxSizerFlags>(hash));

    if(rb_obj_is_kind_of(obj, rb_cWXWindow)) {
        wxWindow *win = unwrap<wxWindow*>(obj);
        if(check_window(_self, win, hash))
            return wrap(_self->Insert(RB_NUM2INT(index), win, flags));
    } else if(rb_obj_is_kind_of(obj, rb_cWXSizer))
        return wrap(_self->Insert(RB_NUM2INT(index),unwrap<wxSizer*>(obj),flags));
    else {
        const wxSize &size = unwrap<wxSize>(obj);
        return wrap(_self->Insert(RB_NUM2INT(index),size.GetWidth(),size.GetHeight(),flags));
    }
    return Qnil;
}

/*
 * call-seq:
 *   insert_spacer(pos, size)
 *
 * inserts a new spacer WX::Sizer::Item into the given position.
 * ===Arguments
 * * pos is Integer
 * * size is a Integer
 * ===Return value
 * WX::Sizer::Item
 */
DLL_LOCAL VALUE _insert_spacer(VALUE self,VALUE idx,VALUE size)
{
    return wrap(_self->InsertSpacer(RB_NUM2UINT(idx),RB_NUM2INT(size)));
}

/*
 * call-seq:
 *   insert_stretch_spacer(pos,[prop])
 *
 * inserts a new stretch spacer WX::Sizer::Item
 * ===Arguments
 * * pos is Integer
 * * prop is a Integer
 * ===Return value
 * WX::Sizer::Item
 */
DLL_LOCAL VALUE _insert_stretch_spacer(int argc,VALUE *argv,VALUE self)
{
    VALUE idx,prop;
    rb_scan_args(argc, argv, "11",&idx,&prop);

    return wrap(_self->InsertStretchSpacer(RB_NUM2UINT(idx),NIL_P(prop) ? 1 : RB_NUM2INT(prop)));
}


/*
 * call-seq:
 *   prepend(window, [options])
 *   prepend(sizer, [options])
 *   prepend(size, [options])
 *
 * prepends a new WX::Sizer::Item
 * ===Arguments
 * * window is a WX::Window
 * * sizer is a WX::Sizer
 * * size is a WX::Size
 *
 * *options: Hash with possible options to set:
 *   * expand true/false says if the element should expand to the whole size
 *   * proportion Integer
 * ===Return value
 * WX::Sizer::Item
 */
DLL_LOCAL VALUE _prepend(int argc,VALUE *argv,VALUE self)
{
    VALUE obj,hash;
    rb_scan_args(argc, argv, "1:",&obj,&hash);

    wxSizerFlags flags(unwrap<wxSizerFlags>(hash));

    if(rb_obj_is_kind_of(obj, rb_cWXWindow)) {
        wxWindow *win = unwrap<wxWindow*>(obj);
        if(check_window(_self, win, hash))
            return wrap(_self->Prepend(win, flags));
    } else if(rb_obj_is_kind_of(obj, rb_cWXSizer))
        return wrap(_self->Prepend(unwrap<wxSizer*>(obj),flags));
    else {
        const wxSize &size = unwrap<wxSize>(obj);
        return wrap(_self->Prepend(size.GetWidth(),size.GetHeight(),flags));
    }
    return Qnil;
}

/*
 * call-seq:
 *   prepend_spacer(size)
 *
 * prepend a new spacer WX::Sizer::Item
 * ===Arguments
 * * size is a Integer
 * ===Return value
 * WX::Sizer::Item
 */
DLL_LOCAL VALUE _prepend_spacer(VALUE self,VALUE size)
{
    return wrap(_self->PrependSpacer(RB_NUM2INT(size)));
}

/*
 * call-seq:
 *   prepend_stretch_spacer([prop])
 *
 * prepends a new stretch spacer WX::Sizer::Item
 * ===Arguments
 * * prop is a Integer
 * ===Return value
 * WX::Sizer::Item
 */
DLL_LOCAL VALUE _prepend_stretch_spacer(int argc,VALUE *argv,VALUE self)
{
    VALUE prop;
    rb_scan_args(argc, argv, "01",&prop);

    return wrap(_self->PrependStretchSpacer(NIL_P(prop) ? 1 : RB_NUM2INT(prop)));
}



DLL_LOCAL VALUE _getItem(VALUE self,VALUE index)
{
    int cidx = RB_NUM2INT(index);
    if(check_index(cidx,_self->GetItemCount()))
        return wrap(_self->GetItem(cidx));
    return Qnil;
}

DLL_LOCAL VALUE _each_size(VALUE self)
{
    return RB_UINT2NUM(_self->GetItemCount());
}


DLL_LOCAL VALUE _each(VALUE self)
{
    RETURN_SIZED_ENUMERATOR(self,0,NULL,RUBY_METHOD_FUNC(_each_size));
    std::size_t  count(_self->GetItemCount());
    for(std::size_t i = 0; i < count; ++i)
        rb_yield(wrap(_self->GetItem(i)));
    return self;
}


DLL_LOCAL VALUE _remove(VALUE self,VALUE index)
{
    rb_check_frozen(self);
    int cidx = RB_NUM2INT(index);
    if(check_index(cidx,_self->GetItemCount()))
        return wrap(_self->Remove(cidx));
    return Qnil;
}


}
}

DLL_LOCAL void Init_WXSizer(VALUE rb_mWX)
{
    using namespace RubyWX::Sizer;
    rb_cWXSizer = rb_define_class_under(rb_mWX,"Sizer",rb_cObject);
    rb_undef_alloc_func(rb_cWXSizer);

    rb_undef_method(rb_cWXSizer,"initialize_copy");
    rb_undef_method(rb_cWXSizer,"_load");
    rb_undef_method(rb_cWXSizer,"_dump");

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

    rb_define_method(rb_cWXSizer,"size",RUBY_METHOD_FUNC(_GetSize),0);
    rb_define_method(rb_cWXSizer,"position",RUBY_METHOD_FUNC(_GetPosition),0);

    rb_define_method(rb_cWXSizer,"layout",RUBY_METHOD_FUNC(_Layout),0);

    rb_define_method(rb_cWXSizer,"add",RUBY_METHOD_FUNC(_add),-1);
    rb_define_method(rb_cWXSizer,"insert",RUBY_METHOD_FUNC(_insert),-1);
    rb_define_method(rb_cWXSizer,"prepend",RUBY_METHOD_FUNC(_prepend),-1);

    rb_define_method(rb_cWXSizer,"add_spacer",RUBY_METHOD_FUNC(_add_spacer),1);
    rb_define_method(rb_cWXSizer,"insert_spacer",RUBY_METHOD_FUNC(_insert_spacer),2);
    rb_define_method(rb_cWXSizer,"prepend_spacer",RUBY_METHOD_FUNC(_prepend_spacer),1);

    rb_define_method(rb_cWXSizer,"add_stretch_spacer",RUBY_METHOD_FUNC(_add_stretch_spacer),-1);
    rb_define_method(rb_cWXSizer,"insert_stretch_spacer",RUBY_METHOD_FUNC(_insert_stretch_spacer),-1);
    rb_define_method(rb_cWXSizer,"prepend_stretch_spacer",RUBY_METHOD_FUNC(_prepend_stretch_spacer),-1);

    rb_define_method(rb_cWXSizer,"[]",RUBY_METHOD_FUNC(_getItem),1);

    rb_define_method(rb_cWXSizer,"each",RUBY_METHOD_FUNC(_each),0);
    rb_include_module(rb_cWXSizer,rb_mEnumerable);

    rb_define_method(rb_cWXSizer,"remove",RUBY_METHOD_FUNC(_remove),1);

    registerInfo<wxSizer>(rb_cWXSizer);

}