static VALUE
sTextSymbol, sTextFieldSymbol, sRadioSymbol, sButtonSymbol,
- sCheckBoxSymbol, sPopUpSymbol, sTextViewSymbol, sViewSymbol,
- sLineSymbol, sTagSymbol, sTypeSymbol, sTitleSymbol, sRadioGroupSymbol,
- sTableSymbol,
+ sCheckBoxSymbol, sToggleButtonSymbol, sPopUpSymbol, sTextViewSymbol,
+ sViewSymbol, sLineSymbol, sTagSymbol, sTypeSymbol, sTitleSymbol,
+ sRadioGroupSymbol, sTableSymbol,
sResizableSymbol, sDialogSymbol, sIndexSymbol,
sXSymbol, sYSymbol, sWidthSymbol, sHeightSymbol,
sOriginSymbol, sSizeSymbol, sFrameSymbol,
sAlignSymbol, sRightSymbol, sCenterSymbol,
sVerticalAlignSymbol, sBottomSymbol,
sMarginSymbol, sPaddingSymbol, sSubItemsSymbol,
- sHFillSymbol, sVFillSymbol,
+ sHFillSymbol, sVFillSymbol, sFlexSymbol,
sIsProcessingActionSymbol,
sFontSymbol,
sDefaultSymbol, sRomanSymbol, sSwissSymbol, sFixedSymbol,
RubyDialogCallback_setStringToItem(view, (val == Qnil ? "" : StringValuePtr(val)));
} else if (type == sPopUpSymbol) {
RubyDialogCallback_setSelectedSubItem(view, NUM2INT(rb_Integer(val)));
- } else if (type == sCheckBoxSymbol || type == sRadioSymbol) {
+ } else if (type == sCheckBoxSymbol || type == sRadioSymbol || type == sToggleButtonSymbol) {
RubyDialogCallback_setStateForItem(view, NUM2INT(rb_Integer(val)));
}
} else if (key == sTitleSymbol) {
frame.size.width = NUM2DBL(rb_Float(Ruby_ObjectAtIndex(val, 2)));
frame.size.height = NUM2DBL(rb_Float(Ruby_ObjectAtIndex(val, 3)));
RubyDialogCallback_setFrameOfItem(view, frame);
+ } else if (key == sFlexSymbol) {
+ /* Glue to [left, top, right, bottom]
+ An array of 4 integers or a string like "LTRB" (case insensitive) */
+ int glue = 0;
+ if (val == Qnil) {
+ rb_ivar_set(self, key_id, val);
+ } else {
+ if (rb_obj_is_kind_of(val, rb_cString)) {
+ const char *sp = StringValuePtr(val);
+ if (strchr(sp, 'l') || strchr(sp, 'L'))
+ glue |= 1;
+ if (strchr(sp, 't') || strchr(sp, 'T'))
+ glue |= 2;
+ if (strchr(sp, 'r') || strchr(sp, 'R'))
+ glue |= 4;
+ if (strchr(sp, 'b') || strchr(sp, 'B'))
+ glue |= 8;
+ } else if (rb_obj_is_kind_of(val, rb_mEnumerable)) {
+ int i;
+ for (i = 0; i < 4; i++) {
+ VALUE gval = Ruby_ObjectAtIndex(val, i);
+ if (RTEST(gval) && NUM2INT(rb_Integer(gval)) != 0)
+ glue |= (1 << i);
+ }
+ } else if (rb_obj_is_kind_of(val, rb_cNumeric)) {
+ glue = NUM2INT(rb_Integer(val));
+ } else {
+ rb_raise(rb_eMolbyError, "the 'glue' attribute should be either an integer, an array of 4 boolean/integers or a string");
+ }
+ rb_ivar_set(self, key_id, INT2NUM(glue));
+ }
} else if (key == sFontSymbol) {
int size, family, style, weight, i;
size = family = style = weight = 0;
int col;
VALUE cval;
val = rb_ary_to_ary(val);
+ for (col = RubyDialogCallback_countTableColumn((RDItem *)view) - 1; col >= 0; col--) {
+ RubyDialogCallback_deleteTableColumn((RDItem *)view, col);
+ }
for (col = 0; col < RARRAY_LEN(val); col++) {
const char *heading;
int format, width, len;
int n = RubyDialogCallback_selectedSubItem(view);
if (n >= 0)
val = INT2NUM(n);
- } else if (type == sCheckBoxSymbol || type == sRadioSymbol) {
+ } else if (type == sCheckBoxSymbol || type == sRadioSymbol || type == sToggleButtonSymbol) {
val = INT2NUM(RubyDialogCallback_getStateForItem(view));
}
} else if (key == sTitleSymbol) {
RDRect frame = RubyDialogCallback_frameOfItem(view);
val = rb_ary_new3(4, rb_float_new(frame.origin.x), rb_float_new(frame.origin.y), rb_float_new(frame.size.width), rb_float_new(frame.size.height));
rb_obj_freeze(val);
+ } else if (key == sFlexSymbol) {
+ int glue;
+ val = rb_ivar_get(self, key_id);
+ if (val != Qnil) {
+ glue = NUM2INT(rb_Integer(val));
+ val = rb_ary_new();
+ rb_ary_push(val, ((glue & 1) ? INT2FIX(1) : INT2FIX(0)));
+ rb_ary_push(val, ((glue & 2) ? INT2FIX(1) : INT2FIX(0)));
+ rb_ary_push(val, ((glue & 4) ? INT2FIX(1) : INT2FIX(0)));
+ rb_ary_push(val, ((glue & 8) ? INT2FIX(1) : INT2FIX(0)));
+ }
} else if (key == sFontSymbol) {
int size, family, style, weight;
VALUE fval, sval, wval;
VALUE items;
int idx = NUM2INT(rb_Integer(ival));
items = rb_iv_get(self, "_items");
- if (idx < 0 || idx >= RARRAY_LEN(items))
+ if (idx < 0 || idx > RARRAY_LEN(items))
rb_raise(rb_eRangeError, "item index (%d) out of range", idx);
+ else if (idx == RARRAY_LEN(items))
+ return Qnil; /* This may happen when this function is called during creation of item */
return RARRAY_PTR(items)[idx];
}
{
VALUE items, oval, *opts, new_item;
int row, col, i, j, n, itag, nitems, *itags;
+ int autoResizeFlag;
RubyDialog *dref;
float *widths, *heights;
float f, fmin;
items = rb_iv_get(self, "_items");
nitems = RARRAY_LEN(items);
+ autoResizeFlag = RubyDialogCallback_isAutoResizeEnabled(dref);
+ RubyDialogCallback_setAutoResizeEnabled(dref, 0);
+
if (argc > 0 && rb_obj_is_kind_of(argv[argc - 1], rb_cHash)) {
VALUE oval1;
oval = argv[argc - 1];
rb_ary_push(items, new_item);
}
+ RubyDialogCallback_setAutoResizeEnabled(dref, autoResizeFlag);
+
return new_item;
}
/*
* call-seq:
+ * size -> [width, height]
+ *
+ * Get the size for this dialog.
+ */
+static VALUE
+s_RubyDialog_Size(VALUE self)
+{
+ RDSize size = RubyDialogCallback_windowSize(s_RubyDialog_GetController(self));
+ return rb_ary_new3(2, INT2NUM(floor(size.width + 0.5)), INT2NUM(floor(size.height + 0.5)));
+}
+
+/*
+ * call-seq:
+ * set_size([width, height])
+ * set_size(width, height)
+ *
+ * Set the size for this dialog.
+ */
+static VALUE
+s_RubyDialog_SetSize(int argc, VALUE *argv, VALUE self)
+{
+ RDSize size;
+ VALUE wval, hval;
+ rb_scan_args(argc, argv, "11", &wval, &hval);
+ if (hval == Qnil) {
+ hval = Ruby_ObjectAtIndex(wval, 1);
+ wval = Ruby_ObjectAtIndex(wval, 0);
+ }
+ size.width = NUM2INT(rb_Integer(wval));
+ size.height = NUM2INT(rb_Integer(hval));
+ RubyDialogCallback_setWindowSize(s_RubyDialog_GetController(self), size);
+ return self;
+}
+
+/*
+ * call-seq:
+ * min_size -> [width, height]
+ *
+ * Get the minimum size for this dialog.
+ */
+static VALUE
+s_RubyDialog_MinSize(VALUE self)
+{
+ RDSize size = RubyDialogCallback_windowMinSize(s_RubyDialog_GetController(self));
+ return rb_ary_new3(2, INT2NUM(floor(size.width + 0.5)), INT2NUM(floor(size.height + 0.5)));
+}
+
+/*
+ * call-seq:
+ * set_min_size
+ * set_min_size([width, height])
+ * set_min_size(width, height)
+ *
+ * Set the minimum size for this dialog.
+ */
+static VALUE
+s_RubyDialog_SetMinSize(int argc, VALUE *argv, VALUE self)
+{
+ RDSize size;
+ VALUE wval, hval;
+ rb_scan_args(argc, argv, "02", &wval, &hval);
+ if (wval == Qnil) {
+ size = RubyDialogCallback_windowSize(s_RubyDialog_GetController(self));
+ } else {
+ if (hval == Qnil) {
+ hval = Ruby_ObjectAtIndex(wval, 1);
+ wval = Ruby_ObjectAtIndex(wval, 0);
+ }
+ size.width = NUM2INT(rb_Integer(wval));
+ size.height = NUM2INT(rb_Integer(hval));
+ }
+ RubyDialogCallback_setWindowMinSize(s_RubyDialog_GetController(self), size);
+ return self;
+}
+
+/*
+ * call-seq:
* save_panel(message = nil, directory = nil, default_filename = nil, wildcard = nil)
*
* Display the "save as" dialog and returns the fullpath filename.
}
}
+int
+RubyDialog_getFlexFlags(RubyValue self, RDItem *ip)
+{
+ VALUE itval, pval;
+ RubyDialog *dref = s_RubyDialog_GetController((VALUE)self);
+ int idx = RubyDialogCallback_indexOfItem(dref, ip);
+ if (idx < 0)
+ return -1; /* No such item (this cannot happen) */
+ itval = s_RubyDialog_ItemAtIndex((VALUE)self, INT2NUM(idx));
+ pval = rb_ivar_get(itval, SYM2ID(sFlexSymbol));
+ if (pval == Qnil)
+ return -1; /* Not set */
+ else return NUM2INT(rb_Integer(pval));
+}
+
#pragma mark ====== Initialize class ======
void
rb_define_method(rb_cDialog, "hide", s_RubyDialog_Hide, 0);
rb_define_method(rb_cDialog, "start_timer", s_RubyDialog_StartTimer, -1);
rb_define_method(rb_cDialog, "stop_timer", s_RubyDialog_StopTimer, 0);
+ rb_define_method(rb_cDialog, "set_size", s_RubyDialog_SetSize, -1);
+ rb_define_method(rb_cDialog, "size", s_RubyDialog_Size, 0);
+ rb_define_method(rb_cDialog, "set_min_size", s_RubyDialog_SetMinSize, -1);
+ rb_define_method(rb_cDialog, "min_size", s_RubyDialog_MinSize, 0);
rb_define_singleton_method(rb_cDialog, "save_panel", s_RubyDialog_SavePanel, -1);
rb_define_singleton_method(rb_cDialog, "open_panel", s_RubyDialog_OpenPanel, -1);
{
static VALUE *sTable1[] = {
&sTextSymbol, &sTextFieldSymbol, &sRadioSymbol, &sButtonSymbol,
- &sCheckBoxSymbol, &sPopUpSymbol, &sTextViewSymbol, &sViewSymbol,
- &sTableSymbol,
+ &sCheckBoxSymbol, &sToggleButtonSymbol, &sPopUpSymbol, &sTextViewSymbol,
+ &sViewSymbol, &sTableSymbol,
&sResizableSymbol, &sDialogSymbol, &sIndexSymbol, &sLineSymbol, &sTagSymbol,
&sTypeSymbol, &sTitleSymbol, &sXSymbol, &sYSymbol,
&sWidthSymbol, &sHeightSymbol, &sOriginSymbol, &sSizeSymbol,
&sValueSymbol, &sRadioGroupSymbol, &sBlockSymbol, &sRangeSymbol,
&sActionSymbol, &sAlignSymbol, &sRightSymbol, &sCenterSymbol,
&sVerticalAlignSymbol, &sBottomSymbol, &sMarginSymbol, &sPaddingSymbol,
- &sSubItemsSymbol, &sHFillSymbol, &sVFillSymbol, &sIsProcessingActionSymbol,
+ &sSubItemsSymbol, &sHFillSymbol, &sVFillSymbol, &sFlexSymbol,
+ &sIsProcessingActionSymbol,
&sFontSymbol, &sDefaultSymbol, &sRomanSymbol, &sSwissSymbol,
&sFixedSymbol, &sNormalSymbol, &sSlantSymbol, &sItalicSymbol,
&sMediumSymbol, &sBoldSymbol, &sLightSymbol,
};
static const char *sTable2[] = {
"text", "textfield", "radio", "button",
- "checkbox", "popup", "textview", "view",
- "table",
+ "checkbox", "togglebutton", "popup", "textview",
+ "view", "table",
"resizable", "dialog", "index", "line", "tag",
"type", "title", "x", "y",
"width", "height", "origin", "size",
"value", "radio_group", "block", "range",
"action", "align", "right", "center",
"vertical_align", "bottom", "margin", "padding",
- "subitems", "hfill", "vfill", "is_processing_action",
+ "subitems", "hfill", "vfill", "flex",
+ "is_processing_action",
"font", "default", "roman", "swiss",
"fixed", "normal", "slant", "italic",
"medium", "bold", "light",
#include "wx/stattext.h"
#include "wx/textctrl.h"
#include "wx/button.h"
+#include "wx/tglbtn.h"
#include "wx/filedlg.h"
#include "wx/dirdlg.h"
#include "wx/dcclient.h"
EVT_TIMER(-1, RubyDialogFrame::OnTimerEvent)
EVT_BUTTON(wxID_OK, RubyDialogFrame::OnDefaultButtonPressed)
EVT_BUTTON(wxID_CANCEL, RubyDialogFrame::OnDefaultButtonPressed)
+ EVT_SIZE(RubyDialogFrame::OnSize)
END_EVENT_TABLE()
RubyDialogFrame::RubyDialogFrame(wxWindow* parent, wxWindowID wid, const wxString& title, const wxPoint& pos, const wxSize& size, long style):
ditems = NULL;
nditems = 0;
dval = NULL;
-
+ mySize = gZeroSize;
+ autoResizeEnabled = true;
+
// Create a vertical box sizer that contains a panel containing all controls and a sizer containing
// OK/Cancel buttons
contentSizer = new wxBoxSizer(wxVERTICAL);
RubyDialog_doTimerAction((RubyValue)dval);
}
+void
+RubyDialogFrame::OnSize(wxSizeEvent &event)
+{
+ wxSize size = GetClientSize();
+ if (mySize.width != 0 && mySize.height != 0 && /*(mySize.width != size.x || mySize.height != size.y) &&*/ autoResizeEnabled) {
+ /* Resize the subviews */
+ int i;
+ for (i = 2; i < nditems; i++) {
+ RDItem *item = ditems[i];
+ int glue = RubyDialog_getFlexFlags((RubyValue)dval, item);
+ if (glue >= 0) {
+ RDRect frame = RubyDialogCallback_frameOfItem(item);
+ switch (glue & 5) {
+ case 5: /* left & right */
+ frame.size.width += size.x - mySize.width;
+ break;
+ case 4: /* right */
+ frame.origin.x += size.x - mySize.width;
+ break;
+ }
+ switch (glue & 10) {
+ case 10: /* top & bottom */
+ frame.size.height += size.y - mySize.height;
+ break;
+ case 8: /* bottom */
+ frame.origin.y += size.y - mySize.height;
+ break;
+ }
+ RubyDialogCallback_setFrameOfItem(item, frame);
+ } else if (wxDynamicCast((wxWindow *)item, wxPanel) != NULL) {
+ wxWindowList & children = ((wxWindow *)item)->GetChildren();
+ wxWindowList::Node *node;
+ wxRect thisRect, origRect, thatRect;
+ int count = 0, dx, dy;
+ origRect = ((wxWindow *)item)->GetRect();
+ for (node = children.GetFirst(); node; node = node->GetNext(), count++) {
+ wxWindow *current = (wxWindow *)node->GetData();
+ thatRect = current->GetRect();
+ if (count == 0) {
+ thisRect = thatRect;
+ continue;
+ }
+ if (thisRect.x > thatRect.x) {
+ thisRect.width += thisRect.x - thatRect.x;
+ thisRect.x = thatRect.x;
+ }
+ if (thisRect.y > thatRect.y) {
+ thisRect.height += thisRect.y - thatRect.y;
+ thisRect.y = thatRect.y;
+ }
+ if (thatRect.x + thatRect.width > thisRect.x + thisRect.width)
+ thisRect.width = thatRect.x + thatRect.width - thisRect.x;
+ if (thatRect.y + thatRect.height > thisRect.y + thisRect.height)
+ thisRect.height = thatRect.y + thatRect.height - thisRect.y;
+ }
+ /* Resize the view, while keeping the subviews at the same window position */
+ dx = thisRect.x;
+ dy = thisRect.y;
+ for (node = children.GetFirst(); node; node = node->GetNext()) {
+ wxWindow *current = (wxWindow *)node->GetData();
+ thatRect = current->GetRect();
+ current->Move(thatRect.x - dx, thatRect.y - dy);
+ }
+ origRect.x += dx;
+ origRect.y += dy;
+ origRect.width = thisRect.width;
+ origRect.height = thisRect.height;
+ ((wxWindow *)item)->SetSize(origRect);
+ }
+ }
+ }
+ mySize.width = size.x;
+ mySize.height = size.y;
+ event.Skip();
+}
+
#pragma mark ====== MyListCtrlDataSource methods ======
int
}
void
+RubyDialogCallback_setWindowMinSize(RubyDialog *dref, RDSize size)
+{
+ wxSize minSize;
+ minSize.x = size.width;
+ minSize.y = size.height;
+ ((RubyDialogFrame *)dref)->SetMinSize(minSize);
+}
+
+RDSize
+RubyDialogCallback_windowSize(RubyDialog *dref)
+{
+ wxSize minSize = ((RubyDialogFrame *)dref)->GetSize();
+ RDSize rminSize;
+ rminSize.width = minSize.GetWidth();
+ rminSize.height = minSize.GetHeight();
+ return rminSize;
+}
+void
RubyDialogCallback_setWindowSize(RubyDialog *dref, RDSize size)
{
wxSize wsize(size.width, size.height);
}
void
+RubyDialogCallback_setAutoResizeEnabled(RubyDialog *dref, int flag)
+{
+ ((RubyDialogFrame *)dref)->SetAutoResizeEnabled(flag);
+}
+
+int
+RubyDialogCallback_isAutoResizeEnabled(RubyDialog *dref)
+{
+ return ((RubyDialogFrame *)dref)->IsAutoResizeEnabled();
+}
+
+void
RubyDialogCallback_createStandardButtons(RubyDialog *dref, const char *oktitle, const char *canceltitle)
{
((RubyDialogFrame *)dref)->CreateStandardButtons(oktitle, canceltitle);
wxButton *bn = new wxButton(parent, -1, tstr, rect.GetPosition(), rect.GetSize());
control = bn;
bn->Connect(-1, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RubyDialogFrame::OnDialogItemAction), NULL, parent);
+ } else if (strcmp(type, "togglebutton") == 0) {
+ /* Button */
+ wxToggleButton *bn = new wxToggleButton(parent, -1, tstr, rect.GetPosition(), rect.GetSize());
+ control = bn;
+ bn->Connect(-1, wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(RubyDialogFrame::OnDialogItemAction), NULL, parent);
} else if (strcmp(type, "popup") == 0) {
/* Popup button (wxChoice) */
wxString du[1] = { _T(" ") };
((wxRadioButton *)item)->SetValue(state);
} else if (wxDynamicCast((wxWindow *)item, wxCheckBox) != NULL) {
((wxCheckBox *)item)->SetValue(state);
+ } else if (wxDynamicCast((wxWindow *)item, wxToggleButton) != NULL) {
+ ((wxToggleButton *)item)->SetValue(state);
}
}
return ((wxRadioButton *)item)->GetValue();
} else if (wxDynamicCast((wxWindow *)item, wxCheckBox) != NULL) {
return ((wxCheckBox *)item)->GetValue();
+ } else if (wxDynamicCast((wxWindow *)item, wxToggleButton) != NULL) {
+ return ((wxToggleButton *)item)->GetValue();
} else return -1;
}
} else return false;
}
+int
+RubyDialogCallback_countTableColumn(RDItem *item)
+{
+ if (wxDynamicCast((wxWindow *)item, MyListCtrl) != NULL) {
+ return ((MyListCtrl *)item)->GetColumnCount();
+ } else return -1;
+}
+
char
RubyDialogCallback_isTableRowSelected(RDItem *item, int row)
{