Преглед изворни кода

More functionality and fixes on FLTK module, and sample application.

mingodad пре 13 година
родитељ
комит
7623dfbca3

+ 93 - 15
SquiLu-ext/sq_fltk.cpp

@@ -71,7 +71,6 @@ struct MyFltkUData {
 CREATE_TAG(Fl);
 CREATE_TAG(Fl_Widget);
 CREATE_TAG(Fl_Progress);
-CREATE_TAG(Fl_Button);
 CREATE_TAG(Fl_Light_Button);
 CREATE_TAG(Fl_Check_Button);
 CREATE_TAG(Fl_Radio_Button);
@@ -575,7 +574,9 @@ static void At_Widget_Destroy(Fl_Widget *widget){
 }
 
 static void fltk_calback_hook(Fl_Widget *sender, void* udata){
-//printf("Sender %p, data %p\n", sender, udata);
+//printf("Sender %p, data %p\n", sender, udata);
+    if(!udata) return;
+    char buf[128];
     HSQUIRRELVM v = (HSQUIRRELVM) Fl::user_data;
     SQInteger savedTop = sq_gettop(v);
     st_mycb *mycb = (st_mycb *)udata;
@@ -583,9 +584,10 @@ static void fltk_calback_hook(Fl_Widget *sender, void* udata){
     sq_pushroottable(v); //’this’ (function environment object)
     if(fltk_get_registered_instance(v, sender) != SQ_OK) sq_pushnull(v);
     sq_pushobject(v, mycb->udata);
-    sq_call(v, 3, SQFalse, SQTrue);
-//printf("%d\n", sq_call(v, 3, SQFalse, SQTrue));
+    int rc = sq_call(v, 3, SQFalse, SQTrue);
+    if(rc != SQ_OK) snprintf(buf, sizeof(buf), "%s", sq_getlasterror_str(v));
     sq_settop(v, savedTop);
+    if(rc != SQ_OK) fl_alert("%s", buf);
 }
 
 static SQRESULT _Fl_Widget_callback(HSQUIRRELVM v)
@@ -634,6 +636,25 @@ static SQRESULT _Fl_Widget_callback(HSQUIRRELVM v)
     }
 	return 0;
 }
+
+static SQRESULT _Fl_Widget_do_callback(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    SETUP_FL_WIDGET(v);
+    if(_top_ > 1){
+        SETUP_FL_WIDGET_AT(v, 2, wdg);
+/*No userdata right now
+        if(_top_ > 2){
+            SQ_GET_INTEGER(v, 3, udata);
+            self->do_callback(wdg, udata);
+        }
+        else
+*/
+        self->do_callback(wdg);
+    }
+    self->do_callback();
+    return 0;
+}
 
 FL_WIDGET_GETSET_INT(align);
 FL_WIDGET_GETSET_INT(argument);
@@ -756,6 +777,24 @@ static SQRESULT _Fl_Widget_image(HSQUIRRELVM v)
     return 1;
 }
 
+static SQRESULT _Fl_Widget_as_group(HSQUIRRELVM v)
+{
+    SETUP_FL_WIDGET(v);
+    Fl_Group *grp = self->as_group();
+    if(grp) return fltk_pushinstance(v, FLTK_TAG(Fl_Group), grp);
+    sq_pushnull(v);
+	return 1;
+}
+
+static SQRESULT _Fl_Widget_as_window(HSQUIRRELVM v)
+{
+    SETUP_FL_WIDGET(v);
+    Fl_Window *win = self->as_window();
+    if(win) return fltk_pushinstance(v, FLTK_TAG(Fl_Window), win);
+    sq_pushnull(v);
+	return 1;
+}
+
 CHEAP_RTTI_FOR(Fl_Widget);
 
 #define _DECL_FUNC(name,nparams,pmask,isStatic) {_SC(#name),_Fl_Widget_##name,nparams,pmask,isStatic}
@@ -767,6 +806,7 @@ static SQRegFunction fl_widget_obj_funcs[]={
 	_DECL_FUNC(argument,-1,_SC("xi"), SQFalse),
 	_DECL_FUNC(box,-1,_SC("xi"), SQFalse),
 	_DECL_FUNC(callback,-1,_SC("xc."), SQFalse),
+	_DECL_FUNC(do_callback,-1,_SC("xx"), SQFalse),
 	_DECL_FUNC(color,-1,_SC("xi"), SQFalse),
 	_DECL_FUNC(selection_color,-1,_SC("xi"), SQFalse),
 	_DECL_FUNC(copy_label,2,_SC("xs"), SQFalse),
@@ -808,6 +848,8 @@ static SQRegFunction fl_widget_obj_funcs[]={
 	_DECL_FUNC(clear_changed2,1,_SC("x"), SQFalse),
 	_DECL_FUNC(clear_changed_all,1,_SC("x"), SQFalse),
 	_DECL_FUNC(take_focus,1,_SC("x"), SQFalse),
+	_DECL_FUNC(as_group,1,_SC("x"), SQFalse),
+	_DECL_FUNC(as_window,1,_SC("x"), SQFalse),
 	{0,0}
 };
 #undef _DECL_FUNC
@@ -866,13 +908,30 @@ static SQRegFunction fl_progress_obj_funcs[]={
 };
 #undef _DECL_FUNC
 
-FLTK_CONSTRUCTOR(Fl_Button);
+MY_FL_CLASS(Fl_Button,
+    int handle(int event){
+        int rc;
+        if(sq_call_fl_virtual_va(this, "handle", "i>i", event, &rc) == 0) return rc;
+        return Fl_Button::handle(event);
+    }
+)
+
 #define SETUP_FL_BUTTON(v) SETUP_FL_KLASS(v, Fl_Button)
-#define FL_BUTTON_GETSET_INT_CAST(funcNAME, typeNAME) FUNC_GETSET_INT(_Fl_Button_, SETUP_FL_BUTTON, self->, funcNAME, typeNAME)
+
+static SQRESULT _MyFl_Button_handle(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SETUP_FL_BUTTON(v);
+    SQ_GET_INTEGER(v, 2, event);
+    sq_pushinteger(v, ((MyFl_Button*)self)->Fl_Button::handle(event));
+    return 1;
+}
+
+#define FL_BUTTON_GETSET_INT_CAST(funcNAME, typeNAME) FUNC_GETSET_INT(_MyFl_Button_, SETUP_FL_BUTTON, self->, funcNAME, typeNAME)
 FL_BUTTON_GETSET_INT_CAST(down_box, Fl_Boxtype);
 FL_BUTTON_GETSET_INT_CAST(value, int);
 
-static SQRESULT _Fl_Button_setonly(HSQUIRRELVM v){
+static SQRESULT _MyFl_Button_setonly(HSQUIRRELVM v){
     SETUP_FL_BUTTON(v);
     self->setonly();
     return 0;
@@ -880,13 +939,14 @@ static SQRESULT _Fl_Button_setonly(HSQUIRRELVM v){
 
 CHEAP_RTTI_FOR(Fl_Button);
 
-#define _DECL_FUNC(name,nparams,pmask,isStatic) {_SC(#name),_Fl_Button_##name,nparams,pmask,isStatic}
+#define _DECL_FUNC(name,nparams,pmask,isStatic) {_SC(#name),_MyFl_Button_##name,nparams,pmask,isStatic}
 static SQRegFunction fl_button_obj_funcs[]={
     CHEAP_RTTI_REG_FUN_FOR(Fl_Button)
 	_DECL_FUNC(constructor,-5,FLTK_constructor_Mask, SQFalse),
 	_DECL_FUNC(down_box,-1,_SC("xi"), SQFalse),
 	_DECL_FUNC(value,-1,_SC("xi"), SQFalse),
 	_DECL_FUNC(setonly,1,_SC("x"), SQFalse),
+	_DECL_FUNC(handle,2,_SC("xi"), SQFalse),
 	{0,0}
 };
 #undef _DECL_FUNC
@@ -1544,6 +1604,15 @@ static SQRESULT _Flu_Tree_Browser_set_hilighted(HSQUIRRELVM v){
     return 0;
 }
 
+static SQRESULT _Flu_Tree_Browser_get_hilighted(HSQUIRRELVM v){
+    SQ_FUNC_VARS_NO_TOP(v);
+    SETUP_FLU_TREE_BROWSER(v);
+    Flu_Tree_Browser::Node* node = self->get_hilighted();
+    if(node) return fltk_pushinstance(v, FLTK_TAG(Flu_Tree_Browser_Node), node);
+    sq_pushnull(v);
+    return 1;
+}
+
 static SQRESULT _Flu_Tree_Browser_clear(HSQUIRRELVM v){
     SETUP_FLU_TREE_BROWSER(v);
     self->clear();
@@ -1552,7 +1621,10 @@ static SQRESULT _Flu_Tree_Browser_clear(HSQUIRRELVM v){
 
 static SQRESULT _Flu_Tree_Browser_get_root(HSQUIRRELVM v){
     SETUP_FLU_TREE_BROWSER(v);
-    return fltk_pushinstance(v, FLTK_TAG(Flu_Tree_Browser_Node), self->get_root());
+    Flu_Tree_Browser::Node* node = self->get_root();
+    if(node) return fltk_pushinstance(v, FLTK_TAG(Flu_Tree_Browser_Node), node);
+    sq_pushnull(v);
+    return 1;
 }
 
 static SQRESULT _Flu_Tree_Browser_add(HSQUIRRELVM v){
@@ -1561,7 +1633,9 @@ static SQRESULT _Flu_Tree_Browser_add(HSQUIRRELVM v){
     SETUP_FLU_TREE_BROWSER_NODE_AT(v, 2, node);
     SQ_GET_STRING(v, 3, label);
     Flu_Tree_Browser::Node* new_node = self->add(node, label);
-    return fltk_pushinstance(v, FLTK_TAG(Flu_Tree_Browser_Node), new_node);
+    if(new_node) return fltk_pushinstance(v, FLTK_TAG(Flu_Tree_Browser_Node), new_node);
+    sq_pushnull(v);
+    return 1;
 }
 
 CHEAP_RTTI_FOR(Flu_Tree_Browser);
@@ -1581,6 +1655,7 @@ static SQRegFunction flu_tree_browser_obj_funcs[]={
 	_DECL_FUNC(clear,1,_SC("x"),SQFalse),
 	_DECL_FUNC(find_by_user_data,2,_SC("xi"),SQFalse),
 	_DECL_FUNC(set_hilighted,2,_SC("xx"),SQFalse),
+	_DECL_FUNC(get_hilighted,1,_SC("x"),SQFalse),
 	_DECL_FUNC(get_root,1,_SC("x"),SQFalse),
 	_DECL_FUNC(add,3,_SC("xxs"),SQFalse),
 	{0,0}
@@ -2761,6 +2836,7 @@ static SQRESULT _Fl_Help_View_link(HSQUIRRELVM v)
 SETUP_FL_HELP_VIEW_GETSET_INT_CAST(textcolor, Fl_Color);
 SETUP_FL_HELP_VIEW_GETSET_INT_CAST(textfont, int);
 SETUP_FL_HELP_VIEW_GETSET_INT_CAST(textsize, int);
+SETUP_FL_HELP_VIEW_GETSET_INT_CAST(scrollbar_size, int);
 
 CHEAP_RTTI_FOR(Fl_Help_View);
 #define _DECL_FUNC(name,nparams,pmask,isStatic) {_SC(#name),_Fl_Help_View_##name,nparams,pmask,isStatic}
@@ -2775,6 +2851,7 @@ static SQRegFunction fl_help_view_obj_funcs[]={
 	_DECL_FUNC(textcolor,-1,_SC("xi"),SQFalse),
 	_DECL_FUNC(textfont,-1,_SC("xi"),SQFalse),
 	_DECL_FUNC(textsize,-1,_SC("xi"),SQFalse),
+	_DECL_FUNC(scrollbar_size,-1,_SC("xi"),SQFalse),
 	{0,0}
 };
 #undef _DECL_FUNC
@@ -3267,24 +3344,25 @@ static SQRESULT _fl_delete_widget(HSQUIRRELVM v)
 	return 0;
 }
 
-static void fltk_cb_hook(void* udata, bool freeAfter){
+static void fltk_cb_hook(void* udata, bool freeAfter){
+    char buf[128];
     HSQUIRRELVM v = (HSQUIRRELVM) Fl::user_data;
     SQInteger savedTop = sq_gettop(v);
     st_mycb *mycb = (st_mycb *)udata;
     sq_pushobject(v, mycb->callback);
     sq_pushroottable(v); //’this’ (function environment object)
     sq_pushobject(v, mycb->udata);
-    sq_call(v, 2, SQFalse, SQTrue);
-
+    int rc = sq_call(v, 2, SQFalse, SQTrue);
+    if(rc != SQ_OK) snprintf(buf, sizeof(buf), "%s", sq_getlasterror_str(v));
     if(freeAfter){
         //cleanup
         sq_release(v, &mycb->callback);
         sq_release(v, &mycb->udata);
         sq_free(mycb, sizeof(st_mycb));
     }
-
     //restore stack
-    sq_settop(v, savedTop);
+    sq_settop(v, savedTop);
+    if(rc != SQ_OK) fl_alert("%s", buf);
 }
 
 static SQRESULT fltk_add_cb(HSQUIRRELVM v, int idx, st_mycb **cb)

+ 1 - 1
SquiLu-ourbiz/help-view-gui.nut

@@ -16,7 +16,7 @@ class HelpWindow extends MyBaseWindow {
   btnFontBigger = null;
   
   constructor(){
-    base.constructor(76, 128, 600, 400);
+    base.constructor(76, 128, 600, 400, _tr("Help"));
     // Create member functions and widgets
     {
       local o = Fl_Tabs(5, 5, 590, 355);

+ 6 - 3
SquiLu-ourbiz/help-view.nut

@@ -15,6 +15,7 @@ class OurHelpWindow extends HelpWindow
 		_help_text_buffer = help_text->buffer();
 		view_html->textsize(view_html->labelsize());
 		view_html->link(hlp_link);
+		view_html->scrollbar_size(fl_width("W").tointeger());
 		btnSavehelp.callback(save_help_file);
 		btnSearchHelp.callback(on_search);
 		words_to_search.callback(on_search);
@@ -49,19 +50,20 @@ class OurHelpWindow extends HelpWindow
 		refresh_html();
 	}
 
-	function save_help_file() {
+	function save_help_file(sender, udata) {
+		this = sender->window();
 		_help_text_buffer->savefile(_help_file_name);
 		btnSavehelp->deactivate();
 	}
 
-	function on_search(){
+	function on_search(sender, udata){
+		this = sender->window();
 		search_help_file(words_to_search->value());
 	}
 
 	function search_help_file(topic, fromStart=false) {
 		words_to_search->value(topic);
 		if(!topic) return;
-
 		if(!_help_text_buffer->length()) load_help_file();
 
 		if(fromStart || words_to_search->changed2()){
@@ -75,6 +77,7 @@ class OurHelpWindow extends HelpWindow
 			foundPos = view_html->find(topic, _last_found_pos);
 			if(foundPos >= 0) _last_found_pos = foundPos;
 			else foundPos = 0;
+			view_html->redraw();
 		}
 		else
 		{

+ 10 - 10
SquiLu-ourbiz/list-search-window.nut

@@ -50,9 +50,9 @@ this->when(FL_WHEN_RELEASE);
     query_limit->textsize(16);
     o->value("50");
   } // Fl_Int_Input* query_limit
-  { btnNotes = new Fl_Button(760, 6, 35, 25, _tr("?"));
+  { btnNotes = new My_Fl_Return_Button(760, 6, 35, 25, _tr("?"));
     btnNotes->labelsize(16);
-  } // Fl_Button* btnNotes
+  } // My_Fl_Return_Button* btnNotes
   topGroup->end();
 } // Fl_Group* topGroup
 { middleGroup = new Fl_Group(0, 41, 800, 409);
@@ -93,22 +93,22 @@ this->when(FL_WHEN_RELEASE);
     search_str->callback(cb_search_str);
     search_str->when(FL_WHEN_ENTER_KEY);
   } // Fl_Input* search_str
-  { btnSearch = new Fl_Button(345, 485, 100, 25, _tr("Search"));
+  { btnSearch = new My_Fl_Return_Button(345, 485, 100, 25, _tr("Search"));
     btnSearch->labelsize(16);
     btnSearch->callback(cb_btnSearch);
-  } // Fl_Button* btnSearch
-  { btnSelect = new Fl_Button(14, 520, 100, 25, _tr("Select"));
+  } // My_Fl_Return_Button* btnSearch
+  { btnSelect = new My_Fl_Return_Button(14, 520, 100, 25, _tr("Select"));
     btnSelect->labelsize(16);
     btnSelect->callback(cb_btnSelect);
-  } // Fl_Button* btnSelect
-  { btnUpdate = new Fl_Button(124, 520, 100, 25, _tr("Update"));
+  } // My_Fl_Return_Button* btnSelect
+  { btnUpdate = new My_Fl_Return_Button(124, 520, 100, 25, _tr("Update"));
     btnUpdate->labelsize(16);
     btnUpdate->callback(cb_btnUpdate);
-  } // Fl_Button* btnUpdate
-  { btnInsert = new Fl_Button(234, 520, 100, 25, _tr("Insert"));
+  } // My_Fl_Return_Button* btnUpdate
+  { btnInsert = new My_Fl_Return_Button(234, 520, 100, 25, _tr("Insert"));
     btnInsert->labelsize(16);
     btnInsert->callback(cb_btnInsert);
-  } // Fl_Button* btnInsert
+  } // My_Fl_Return_Button* btnInsert
   { btnThumbImage = new Fl_Image_Box(663, 445, 125, 105);
     btnThumbImage->box(FL_NO_BOX);
     btnThumbImage->color(FL_BACKGROUND_COLOR);

+ 82 - 82
SquiLu-ourbiz/main-window.nut

@@ -58,105 +58,105 @@ constructor(px, py, pw, ph, pl) {
 	  { tabSales = new Fl_Group(5, 35, 320, 280, _tr("Sales"));
 	    tabSales->color(127);
 	    tabSales->labelsize(16);
-	    { btnOrdersSales = new Fl_Button(30, 50, 275, 55, _tr("Sales"));
+	    { btnOrdersSales = new My_Fl_Return_Button(30, 50, 275, 55, _tr("Sales"));
 	      btnOrdersSales->labeltype(FL_SHADOW_LABEL);
 	      btnOrdersSales->labelfont(3);
 	      btnOrdersSales->labelsize(34);
 	      btnOrdersSales->labelcolor(FL_INACTIVE_COLOR);
 	      btnOrdersSales->callback(cb_btnOrdersSales);
 	      btnOrdersSales->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
-	    } // Fl_Button* btnOrdersSales
-	    { btnPaymentsSales = new Fl_Button(30, 116, 275, 55, _tr("Payments"));
+	    } // My_Fl_Return_Button* btnOrdersSales
+	    { btnPaymentsSales = new My_Fl_Return_Button(30, 116, 275, 55, _tr("Payments"));
 	      btnPaymentsSales->labeltype(FL_SHADOW_LABEL);
 	      btnPaymentsSales->labelfont(3);
 	      btnPaymentsSales->labelsize(34);
 	      btnPaymentsSales->labelcolor(FL_INACTIVE_COLOR);
 	      btnPaymentsSales->callback(cb_btnPaymentsSales);
-	    } // Fl_Button* btnPaymentsSales
-	    { btnEntitiesSales = new Fl_Button(30, 183, 275, 55, _tr("Customers"));
+	    } // My_Fl_Return_Button* btnPaymentsSales
+	    { btnEntitiesSales = new My_Fl_Return_Button(30, 183, 275, 55, _tr("Customers"));
 	      btnEntitiesSales->labeltype(FL_SHADOW_LABEL);
 	      btnEntitiesSales->labelfont(3);
 	      btnEntitiesSales->labelsize(34);
 	      btnEntitiesSales->labelcolor(FL_INACTIVE_COLOR);
 	      btnEntitiesSales->callback(cb_btnEntitiesSales);
-	    } // Fl_Button* btnEntitiesSales
-	    { btnProductsSales = new Fl_Button(30, 250, 275, 55, _tr("Products"));
+	    } // My_Fl_Return_Button* btnEntitiesSales
+	    { btnProductsSales = new My_Fl_Return_Button(30, 250, 275, 55, _tr("Products"));
 	      btnProductsSales->labeltype(FL_SHADOW_LABEL);
 	      btnProductsSales->labelfont(3);
 	      btnProductsSales->labelsize(34);
 	      btnProductsSales->labelcolor(FL_INACTIVE_COLOR);
 	      btnProductsSales->callback(cb_btnProductsSales);
-	    } // Fl_Button* btnProductsSales
+	    } // My_Fl_Return_Button* btnProductsSales
 	    tabSales->end();
 	  } // Fl_Group* tabSales
 	  { tabBuys = new Fl_Group(5, 35, 320, 280, _tr("Buys"));
 	    tabBuys->color(174);
 	    tabBuys->labelsize(16);
 	    tabBuys->hide();
-	    { btnOrdersBuys = new Fl_Button(30, 50, 275, 55, _tr("Buys"));
+	    { btnOrdersBuys = new My_Fl_Return_Button(30, 50, 275, 55, _tr("Buys"));
 	      btnOrdersBuys->labeltype(FL_SHADOW_LABEL);
 	      btnOrdersBuys->labelfont(3);
 	      btnOrdersBuys->labelsize(34);
 	      btnOrdersBuys->labelcolor(FL_INACTIVE_COLOR);
 	      btnOrdersBuys->callback(cb_btnOrdersBuys);
 	      btnOrdersBuys->align((FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
-	    } // Fl_Button* btnOrdersBuys
-	    { btnPaymentsBuys = new Fl_Button(30, 115, 275, 55, _tr("Payments"));
+	    } // My_Fl_Return_Button* btnOrdersBuys
+	    { btnPaymentsBuys = new My_Fl_Return_Button(30, 115, 275, 55, _tr("Payments"));
 	      btnPaymentsBuys->labeltype(FL_SHADOW_LABEL);
 	      btnPaymentsBuys->labelfont(3);
 	      btnPaymentsBuys->labelsize(34);
 	      btnPaymentsBuys->labelcolor(FL_INACTIVE_COLOR);
 	      btnPaymentsBuys->callback(cb_btnPaymentsBuys);
-	    } // Fl_Button* btnPaymentsBuys
-	    { btnProductsBuys = new Fl_Button(30, 250, 275, 55, _tr("Products"));
+	    } // My_Fl_Return_Button* btnPaymentsBuys
+	    { btnProductsBuys = new My_Fl_Return_Button(30, 250, 275, 55, _tr("Products"));
 	      btnProductsBuys->labeltype(FL_SHADOW_LABEL);
 	      btnProductsBuys->labelfont(3);
 	      btnProductsBuys->labelsize(34);
 	      btnProductsBuys->labelcolor(FL_INACTIVE_COLOR);
 	      btnProductsBuys->callback(cb_btnProductsBuys);
-	    } // Fl_Button* btnProductsBuys
-	    { btnEntitiesBuys = new Fl_Button(30, 183, 275, 55, _tr("Suppliers"));
+	    } // My_Fl_Return_Button* btnProductsBuys
+	    { btnEntitiesBuys = new My_Fl_Return_Button(30, 183, 275, 55, _tr("Suppliers"));
 	      btnEntitiesBuys->labeltype(FL_SHADOW_LABEL);
 	      btnEntitiesBuys->labelfont(3);
 	      btnEntitiesBuys->labelsize(34);
 	      btnEntitiesBuys->labelcolor(FL_INACTIVE_COLOR);
 	      btnEntitiesBuys->callback(cb_btnEntitiesBuys);
-	    } // Fl_Button* btnEntitiesBuys
+	    } // My_Fl_Return_Button* btnEntitiesBuys
 	    tabBuys->end();
 	  } // Fl_Group* tabBuys
 	  { tabAll = new Fl_Group(5, 35, 320, 280, _tr("All"));
 	    tabAll->color(239);
 	    tabAll->labelsize(16);
 	    tabAll->hide();
-	    { btnOrders = new Fl_Button(30, 50, 275, 55, _tr("Orders"));
+	    { btnOrders = new My_Fl_Return_Button(30, 50, 275, 55, _tr("Orders"));
 	      btnOrders->labeltype(FL_SHADOW_LABEL);
 	      btnOrders->labelfont(3);
 	      btnOrders->labelsize(34);
 	      btnOrders->labelcolor(FL_INACTIVE_COLOR);
 	      btnOrders->callback(cb_btnOrders);
 	      btnOrders->align((FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
-	    } // Fl_Button* btnOrders
-	    { btnPayments = new Fl_Button(30, 116, 275, 55, _tr("Payments"));
+	    } // My_Fl_Return_Button* btnOrders
+	    { btnPayments = new My_Fl_Return_Button(30, 116, 275, 55, _tr("Payments"));
 	      btnPayments->labeltype(FL_SHADOW_LABEL);
 	      btnPayments->labelfont(3);
 	      btnPayments->labelsize(34);
 	      btnPayments->labelcolor(FL_INACTIVE_COLOR);
 	      btnPayments->callback(cb_btnPayments);
-	    } // Fl_Button* btnPayments
-	    { btnEntities = new Fl_Button(30, 183, 275, 55, _tr("Entities"));
+	    } // My_Fl_Return_Button* btnPayments
+	    { btnEntities = new My_Fl_Return_Button(30, 183, 275, 55, _tr("Entities"));
 	      btnEntities->labeltype(FL_SHADOW_LABEL);
 	      btnEntities->labelfont(3);
 	      btnEntities->labelsize(34);
 	      btnEntities->labelcolor(FL_INACTIVE_COLOR);
 	      btnEntities->callback(cb_btnEntities);
-	    } // Fl_Button* btnEntities
-	    { btnProducts = new Fl_Button(30, 250, 275, 55, _tr("Products"));
+	    } // My_Fl_Return_Button* btnEntities
+	    { btnProducts = new My_Fl_Return_Button(30, 250, 275, 55, _tr("Products"));
 	      btnProducts->labeltype(FL_SHADOW_LABEL);
 	      btnProducts->labelfont(3);
 	      btnProducts->labelsize(34);
 	      btnProducts->labelcolor(FL_INACTIVE_COLOR);
 	      btnProducts->callback(cb_btnProducts);
-	    } // Fl_Button* btnProducts
+	    } // My_Fl_Return_Button* btnProducts
 	    tabAll->end();
 	    Fl_Group.current()->resizable(tabAll);
 	  } // Fl_Group* tabAll
@@ -164,28 +164,28 @@ constructor(px, py, pw, ph, pl) {
 	    tabGL->color(132);
 	    tabGL->labelsize(16);
 	    tabGL->hide();
-	    { btnGLGroups = new Fl_Button(30, 50, 275, 55, _tr("Groups"));
+	    { btnGLGroups = new My_Fl_Return_Button(30, 50, 275, 55, _tr("Groups"));
 	      btnGLGroups->labeltype(FL_SHADOW_LABEL);
 	      btnGLGroups->labelfont(3);
 	      btnGLGroups->labelsize(34);
 	      btnGLGroups->labelcolor(FL_INACTIVE_COLOR);
 	      btnGLGroups->callback(cb_btnGLGroups);
 	      btnGLGroups->align((FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
-	    } // Fl_Button* btnGLGroups
-	    { btnGLChart = new Fl_Button(30, 115, 275, 55, _tr("Chart"));
+	    } // My_Fl_Return_Button* btnGLGroups
+	    { btnGLChart = new My_Fl_Return_Button(30, 115, 275, 55, _tr("Chart"));
 	      btnGLChart->labeltype(FL_SHADOW_LABEL);
 	      btnGLChart->labelfont(3);
 	      btnGLChart->labelsize(34);
 	      btnGLChart->labelcolor(FL_INACTIVE_COLOR);
 	      btnGLChart->callback(cb_btnGLChart);
-	    } // Fl_Button* btnGLChart
-	    { btnGLTransactions = new Fl_Button(30, 180, 275, 55, _tr("Transactions"));
+	    } // My_Fl_Return_Button* btnGLChart
+	    { btnGLTransactions = new My_Fl_Return_Button(30, 180, 275, 55, _tr("Transactions"));
 	      btnGLTransactions->labeltype(FL_SHADOW_LABEL);
 	      btnGLTransactions->labelfont(3);
 	      btnGLTransactions->labelsize(34);
 	      btnGLTransactions->labelcolor(FL_INACTIVE_COLOR);
 	      btnGLTransactions->callback(cb_btnGLTransactions);
-	    } // Fl_Button* btnGLTransactions
+	    } // My_Fl_Return_Button* btnGLTransactions
 	    tabGL->end();
 	  } // Fl_Group* tabGL
 	  { tabConfig = new Fl_Group(5, 35, 320, 280, _tr("Config"));
@@ -195,59 +195,59 @@ constructor(px, py, pw, ph, pl) {
 	      config_scroll->labelsize(16);
 	      { local o = config_pack = new Fl_Pack(30, 45, 270, 260);
 		config_pack->labelsize(16);
-		{ btnOrdersSum = new Fl_Button(65, 55, 64, 30, _tr("Orders Sum"));
+		{ btnOrdersSum = new My_Fl_Return_Button(65, 55, 64, 30, _tr("Orders Sum"));
 		  btnOrdersSum->labelsize(16);
 		  btnOrdersSum->callback(cb_btnOrdersSum);
-		} // Fl_Button* btnOrdersSum
-		{ btnSalesTaxRates = new Fl_Button(55, 45, 64, 30, _tr("Sales Tax Rates"));
+		} // My_Fl_Return_Button* btnOrdersSum
+		{ btnSalesTaxRates = new My_Fl_Return_Button(55, 45, 64, 30, _tr("Sales Tax Rates"));
 		  btnSalesTaxRates->labelsize(16);
 		  btnSalesTaxRates->callback(cb_btnSalesTaxRates);
-		} // Fl_Button* btnSalesTaxRates
-		{ btnOrderTypes = new Fl_Button(65, 80, 64, 30, _tr("Order Types"));
+		} // My_Fl_Return_Button* btnSalesTaxRates
+		{ btnOrderTypes = new My_Fl_Return_Button(65, 80, 64, 30, _tr("Order Types"));
 		  btnOrderTypes->labelsize(16);
 		  btnOrderTypes->callback(cb_btnOrderTypes);
-		} // Fl_Button* btnOrderTypes
-		{ btnPaymentTypes = new Fl_Button(105, 148, 64, 30, _tr("Payment Types"));
+		} // My_Fl_Return_Button* btnOrderTypes
+		{ btnPaymentTypes = new My_Fl_Return_Button(105, 148, 64, 30, _tr("Payment Types"));
 		  btnPaymentTypes->labelsize(16);
 		  btnPaymentTypes->callback(cb_btnPaymentTypes);
-		} // Fl_Button* btnPaymentTypes
-		{ btnMeasureUnits = new Fl_Button(115, 158, 64, 30, _tr("Measure Units"));
+		} // My_Fl_Return_Button* btnPaymentTypes
+		{ btnMeasureUnits = new My_Fl_Return_Button(115, 158, 64, 30, _tr("Measure Units"));
 		  btnMeasureUnits->labelsize(16);
 		  btnMeasureUnits->callback(cb_btnMeasureUnits);
-		} // Fl_Button* btnMeasureUnits
-		{ btnWarrantyTypes = new Fl_Button(125, 168, 64, 30, _tr("Warranty Types"));
+		} // My_Fl_Return_Button* btnMeasureUnits
+		{ btnWarrantyTypes = new My_Fl_Return_Button(125, 168, 64, 30, _tr("Warranty Types"));
 		  btnWarrantyTypes->labelsize(16);
 		  btnWarrantyTypes->callback(cb_btnWarrantyTypes);
-		} // Fl_Button* btnWarrantyTypes
-		{ btnImages = new Fl_Button(75, 118, 64, 30, _tr("Images"));
+		} // My_Fl_Return_Button* btnWarrantyTypes
+		{ btnImages = new My_Fl_Return_Button(75, 118, 64, 30, _tr("Images"));
 		  btnImages->labelsize(16);
 		  btnImages->callback(cb_btnImages);
-		} // Fl_Button* btnImages
-		{ btnProductGroups = new Fl_Button(85, 128, 64, 30, _tr("Product Groups"));
+		} // My_Fl_Return_Button* btnImages
+		{ btnProductGroups = new My_Fl_Return_Button(85, 128, 64, 30, _tr("Product Groups"));
 		  btnProductGroups->labelsize(16);
 		  btnProductGroups->callback(cb_btnProductGroups);
-		} // Fl_Button* btnProductGroups
-		{ btnEntityGroups = new Fl_Button(95, 138, 64, 30, _tr("Entity Groups"));
+		} // My_Fl_Return_Button* btnProductGroups
+		{ btnEntityGroups = new My_Fl_Return_Button(95, 138, 64, 30, _tr("Entity Groups"));
 		  btnEntityGroups->labelsize(16);
 		  btnEntityGroups->callback(cb_btnEntityGroups);
-		} // Fl_Button* btnEntityGroups
-		{ btnConfig = new Fl_Button(105, 148, 64, 30, _tr("App Config"));
+		} // My_Fl_Return_Button* btnEntityGroups
+		{ btnConfig = new My_Fl_Return_Button(105, 148, 64, 30, _tr("App Config"));
 		  btnConfig->labelsize(16);
 		  btnConfig->callback(cb_btnConfig);
-		} // Fl_Button* btnConfig
-		{ btnOpenDB = new Fl_Button(115, 158, 64, 30, _tr("Open Database"));
+		} // My_Fl_Return_Button* btnConfig
+		{ btnOpenDB = new My_Fl_Return_Button(115, 158, 64, 30, _tr("Open Database"));
 		  btnOpenDB->tooltip(_tr("Open a database file"));
 		  btnOpenDB->labelsize(16);
 		  btnOpenDB->callback(cb_btnOpenDB);
-		} // Fl_Button* btnOpenDB
-		{ btnTranslations = new Fl_Button(115, 158, 64, 30, _tr("Translations"));
+		} // My_Fl_Return_Button* btnOpenDB
+		{ btnTranslations = new My_Fl_Return_Button(115, 158, 64, 30, _tr("Translations"));
 		  btnTranslations->labelsize(16);
 		  btnTranslations->callback(cb_btnTranslations);
-		} // Fl_Button* btnTranslations
-		{ btnAppUsers = new Fl_Button(75, 65, 64, 30, _tr("App Users"));
+		} // My_Fl_Return_Button* btnTranslations
+		{ btnAppUsers = new My_Fl_Return_Button(75, 65, 64, 30, _tr("App Users"));
 		  btnAppUsers->labelsize(16);
 		  btnAppUsers->callback(cb_btnAppUsers);
-		} // Fl_Button* btnAppUsers
+		} // My_Fl_Return_Button* btnAppUsers
 		{ btnAskForPrinter = new Fl_Check_Button(55, 70, 64, 15, _tr("Ask for Printer"));
 		  btnAskForPrinter->down_box(FL_DOWN_BOX);
 		} // Fl_Check_Button* btnAskForPrinter
@@ -267,60 +267,60 @@ constructor(px, py, pw, ph, pl) {
 }
 
 function cb_btnEntitiesSales(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Entities Sales List/Search", EntitiesListSearch);
+	this = sender.window();
+	local win = showChildWindow("Entities Sales List/Search", EntitiesListSearch);
 }
 function cb_btnPaymentsSales(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Payments Sales List/Search", PaymentsListSearch);
+	this = sender.window();
+	local win = showChildWindow("Payments Sales List/Search", PaymentsListSearch);
 }
 function cb_btnOrdersSales(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Orders Sales List/Search", OrdersListSearch);
+	this = sender.window();
+	local win = showChildWindow("Orders Sales List/Search", OrdersListSearch);
 }
 function cb_btnProductsSales(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Products Sales List/Search", ProductsListSearch);
+	this = sender.window();
+	local win = showChildWindow("Products Sales List/Search", ProductsListSearch);
 }
 function cb_btnOrdersBuys(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Orders Buys List/Search", OrdersListSearch);
+	this = sender.window();
+	local win = showChildWindow("Orders Buys List/Search", OrdersListSearch);
 }
 function cb_btnPaymentsBuys(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Payments Buys List/Search", PaymentsListSearch);
+	this = sender.window();
+	local win = showChildWindow("Payments Buys List/Search", PaymentsListSearch);
 }
 function cb_btnProductsBuys(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Products Buys List/Search", ProductsListSearch);
+	this = sender.window();
+	local win = showChildWindow("Products Buys List/Search", ProductsListSearch);
 }
 function cb_btnEntitiesBuys(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Entities Buys List/Search", EntitiesListSearch);
+	this = sender.window();
+	local win = showChildWindow("Entities Buys List/Search", EntitiesListSearch);
 }
 function cb_btnOrders(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Orders List/Search", OrdersListSearch);
+	this = sender.window();
+	local win = showChildWindow("Orders List/Search", OrdersListSearch);
 }
 function cb_btnPayments(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Payments List/Search", PaymentsListSearch);
+	this = sender.window();
+	local win = showChildWindow("Payments List/Search", PaymentsListSearch);
 }
 function cb_btnEntities(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Entities List/Search", EntitiesListSearch);
+	this = sender.window();
+	local win = showChildWindow("Entities List/Search", EntitiesListSearch);
 }
 function cb_btnProducts(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Products List/Search", ProductsListSearch);
+	this = sender.window();
+	local win = showChildWindow("Products List/Search", ProductsListSearch);
 }
 function cb_btnGLGroups(){print(__LINE__);}
 function cb_btnGLChart(){print(__LINE__);}
 function cb_btnGLTransactions(){print(__LINE__);}
 function cb_btnOrdersSum(){print(__LINE__);}
 function cb_btnSalesTaxRates(sender, udata){
-	local pr = sender.parent_root();
-	local win = pr.showChildWindow("Sales Tax Rates List/Edit", OurSalesTax);
+	this = sender.window();
+	local win = showChildWindow("Sales Tax Rates List/Edit", OurSalesTax);
 }
 function cb_btnOrderTypes(){print(__LINE__);}
 function cb_btnPaymentTypes(){print(__LINE__);}

+ 11 - 3
SquiLu-ourbiz/ourbiz-client.nut

@@ -125,11 +125,13 @@ class HTTPConnAuthBase extends HTTPConnBase
     function response_begin( r )
     {
         base.response_begin(r);
+/*
         if(my_status != 200)
         {
 	    //foreach(k,v in get_last_stackinfo()) print(k,v)
             throw (format("HTTP Error %d", my_status));
         }
+*/
     }
 
     function send_my_request(method, uri, body=null, bodysize=null, boundary=null, useSLE=false)
@@ -171,7 +173,10 @@ class HTTPConnAuthBase extends HTTPConnBase
                 }
                 else if(my_status == 200)
                         break;
-                else throw e;
+                else {
+			//foreach(k,v in get_last_stackinfo()) print(k, v);
+			throw e;
+		}
             }
         }
     }
@@ -442,8 +447,11 @@ class AppServer
 	local ar = [];
 	pos = sle2vecOfvec(sle_str, ar, pos);
 	local keys = ar[0];
-	local values = ar[1];
-	foreach(idx, k in keys) rec[k] <- values[idx];
+	if(ar.len() > 1){
+		local values = ar[1];
+		foreach(idx, k in keys) rec[k] <- values[idx];
+	}
+	else foreach(idx, k in keys) rec[k] <- null;
 	return pos;
     }
     

+ 145 - 62
SquiLu-ourbiz/ourbiz-fltk.nut

@@ -131,6 +131,21 @@ class My_Fl_Return_Button extends Fl_Button {
 	constructor(px, py, pw, ph, pl=""){
 		base.constructor(px, py, pw, ph, pl);
 	}
+	function handle(event)
+	{
+		if(event == FL_KEYBOARD)
+		{
+
+		    switch(Fl.event_key())
+		    {
+		    case FL_Enter:
+		    case FL_KP_Enter:
+			do_callback();
+			return 0;
+		    }
+		}
+		return base.handle(event);
+	}
 }
 
 class Fl_Choice_Int extends Fl_Choice {
@@ -231,20 +246,23 @@ class MyBaseWindow extends Fl_Window {
 		childWindows = {};
 		_db_map = {};
 	}
+	
+	function show_help_window(sender=null, udata=null){
+		if(sender) this = sender->window();
+		if(!app_help_window){
+			app_help_window = OurHelpWindow();
+		}
+		app_help_window.show();
+		//Fl_Group *grp = wdg->as_group();
+		app_help_window->search_help_file(label(), true);
+	}
 
 	function handle(event){
 		if(event == FL_KEYBOARD && Fl.event_command() == 0){
 			local key = Fl.event_key();
 			switch(key){
 				//case FL_Menu:  menu_bar_navigate();break;
-				case FL_F+1:
-					if(!app_help_window){
-						app_help_window = OurHelpWindow();
-					}
-					app_help_window.show();
-					//Fl_Group *grp = wdg->as_group();
-					app_help_window->search_help_file(label(), true);
-				break;
+				case FL_F+1: show_help_window(); break;
 			}
 		}
 		return base.handle(event);
@@ -353,6 +371,7 @@ class MyBaseWindow extends Fl_Window {
 	function insert_group_tree_childs (tree, node, parent, pos, size, data)
 	{
 	    local new_node;
+	    assert(node);
 	    while(pos < size)
 	    {
 		local rec = data[pos];
@@ -363,7 +382,7 @@ class MyBaseWindow extends Fl_Window {
 		local str = rec[2].gsub("/", "\\/");
 		new_node = tree->add(node, str);
 		if(new_node) new_node->user_data(id);
-			else throw ("Try to insert an invalid Tree Node.");
+		else throw ("Try to insert an invalid Tree Node : " + str);
 
 		++pos;
 		pos = insert_group_tree_childs(tree, new_node, id, pos, size, data);
@@ -390,7 +409,13 @@ class MyBaseWindow extends Fl_Window {
 		appServer.get_list_data(data, _table_name , 0, 0);
 		local pos = 0;
 		if(!node) node = tree->get_root();
-		insert_group_tree_childs(tree, node, 0, pos, data.size(), data);
+		insert_group_tree_childs(tree, node, parent, pos, data.size(), data);
+	}
+	function delete_on_window_close_cb (sender, udata){
+		if(sender){
+			if(!sender.as_window()) throw(_tr("Only windows can use this callback !"));
+			Fl.delete_widget(sender);
+		}
 	}
 }
 
@@ -919,7 +944,7 @@ class Fl_Data_Table extends Flv_Data_Table {
 	}
 	function get_row_id(arow=null){
 		if(arow == null) arow = row();
-		return _data[arow][0];
+		return _data[arow][0].tointeger();
 	}
 }
 
@@ -1024,45 +1049,73 @@ class MyListSearchWindow extends ListSearch {
 		grid->callback_when(FLVEcb_ROW_CHANGED | FLVEcb_CLICKED | FLVEcb_ROW_HEADER_CLICKED);
 		grid->callback(grid_cb);
 		grid->_call_this = this;
+		btnSelect->deactivate();
+		btnNotes.callback(show_help_window);
 	}
 
+	function cb_btnUpdate(sender, udata){
+		this = sender->window();
+		row_selected(Fl_Data_Table_Events.e_update);
+	}
+	function cb_btnInsert(sender, udata){
+		this = sender->window();
+		row_selected(Fl_Data_Table_Events.e_insert);
+	}
 	function grid_cb(sender, udata){}
 	function get_edit_window(){return null;}
+	
+	function show_edit_window(edit_id){
+		local win = get_edit_window();
+		win.show();
+		win.do_edit(edit_id);
+	}
 
 	function row_selected(ev){
-		local edit_window = get_edit_window();
-		if(edit_window){
-			edit_window.show();
-			edit_window.do_edit(grid->get_row_id());
-			switch(ev){
-				case Fl_Data_Table_Events.e_select:
-				break;
-				case Fl_Data_Table_Events.e_insert:
-				break;
-				case Fl_Data_Table_Events.e_update:
-				break;
-				case Fl_Data_Table_Events.e_delete:
-				break;
-			}
+		switch(ev){
+			case Fl_Data_Table_Events.e_select:
+			break;
+			case Fl_Data_Table_Events.e_insert:
+				show_edit_window(0);
+			break;
+			case Fl_Data_Table_Events.e_update:
+				show_edit_window(grid->get_row_id());
+			break;
+			case Fl_Data_Table_Events.e_delete:
+				show_edit_window(grid->get_row_id());
+			break;
 		}
 	}
 
-	function get_search_data(data){}
-	function fill_grid(){
+	function get_search_data(data, search_otions){}
+	function get_search_options(){ return null;}
+	function fill_grid(search_otions = null){
 		local cursor_wait = fl_cursor_wait();
+		if(!search_otions) search_otions = get_search_options();
 		grid->clear_data_rows();
-		get_search_data(grid->_data);
+		get_search_data(grid->_data, search_otions);
 		grid->recalc_data();
 	}
+	function cb_search_str(sender, udata){
+		this = sender->window();
+		cb_btnSearch(sender, udata);
+	}
 	function cb_btnSearch(sender, udata){
 		this = sender.window();
 		fill_grid();
+		delayed_focus(grid);
 	}
 
 	function create_search_by0(name, Klass, pack){
-		local sb = Klass(0,0,25,20, _tr(name));
-		sb->labelsize(pack->labelsize());
-		sb->w(fl_width(sb.label()) + fl_width("W"));
+		local name_tr = _tr(name);
+		local sb = Klass(0,0,25,20, name_tr);
+		local label_font = pack->labelfont();
+		local label_size = pack->labelsize();
+		sb->labelsize(label_size);
+		local saved_font = fl_font();
+		local saved_font_size = fl_size();
+		fl_font(label_font, label_size);
+		sb->w(fl_width(name_tr) + fl_width("W"));
+		fl_font(saved_font, saved_font_size);
 		pack->add(sb);
 		return sb;
 	}
@@ -1290,8 +1343,9 @@ class EntitiesListSearch extends MyListSearchWindow {
 	_search_by_product = null;
 	_search_by_id = null;
 	_search_by_active = null;
+	_sales_orders_list = null;
 
-	constructor() {
+	constructor(doInitialSearch=true) {
 		base.constructor();
 		label(_tr("Entities List Search"));
 		local cols_info = [
@@ -1311,12 +1365,12 @@ class EntitiesListSearch extends MyListSearchWindow {
 		_search_by_active = create_search_by2("Active");
 		_search_by_name->setonly();
 		_search_by_active->value(1);
-		fill_grid();
+		if(doInitialSearch) delayed_method_call(this, this.fill_grid, null);
 	}
 	function fill_search_options(){
 		pack_search_options.add(Fl_Radio_Button());
 	}
-	function get_search_data(data){
+	function get_search_options(){
 		_search_options.search_str = search_str.value();
 		_search_options.name = _search_by_name.value() == 1;
 		_search_options.notes = _search_by_notes.value() == 1;
@@ -1325,17 +1379,50 @@ class EntitiesListSearch extends MyListSearchWindow {
 		_search_options.id = _search_by_id.value() == 1;
 		_search_options.active = _search_by_active.value() == 1;
 		_search_options.group_id = group_filter->get_data_at();
-		appServer.entities_get_list(grid->_data, _search_options);
+		return _search_options;
+	}
+	function get_search_data(data, so){
+		appServer.entities_get_list(grid->_data, so);
 	}
 
 	function get_edit_window(){return getChildWindow("Entity Edit", MyEditEntityWindow);}
+	function mk_popup()
+	{
+		_popup = create_popup_menu_for(grid, grid->global_style().height());
+		_popup.callback(on_popupmenu_cb);
 
-	function cb_btnInsert(sender, udata){
-		this = sender.window();
-		local win = showChildWindow("Entity Edit", EditEntitiesWindow);
+		_popup->add(_tr("Orders"));
+		_popup->add(_tr("Products"));
 	}
-	function cb_btnUpdate(sender, udata){
-		print_entities_list_contact_report();
+
+	function on_popupmenu_cb(sender, udata){
+		this = sender.window();
+		local row = grid->row();
+		if(row < 0) return;
+		switch(_popup->value()){
+			case 0:{
+				_sales_orders_list = OrdersListSearch(false);
+				//_sales_orders_list.callback(delete_on_window_close_cb);
+				local so = OurBizSearchOptions();
+				so.entity_id = grid->get_row_id(row);
+				so.sales = _search_options.sales;
+				so.buys = _search_options.buys;
+				_sales_orders_list->fill_grid(so);
+				_sales_orders_list->show();
+			}
+			break;
+			case 1:{
+				local products_list = ProductsListSearch();
+				//products_list.callback(delete_on_window_close_cb);
+				local so = OurBizSearchOptions();
+				so.entity_id = grid->get_row_id(row);
+				so.sales = _search_options.sales;
+				so.buys = _search_options.buys;
+				products_list->fill_grid(so);
+				products_list->show();
+			}
+			break;
+		}
 	}
 }
 
@@ -1470,7 +1557,7 @@ class MyEditProductWindow extends EditProductWindow {
 	function load_aux_data(){
 		local tree = db_products_group_id;
 		setup_tree_browser_for_selection(tree);
-		treeLoadChilds(tree, 0, 0, "product_groups");
+		treeLoadChilds(tree, null, 0, "product_groups");
 
 		local sales_tax_data = [], measure_units_data = [], warranty_data = [];
 
@@ -1519,7 +1606,7 @@ class ProductsListSearch extends MyListSearchWindow {
 	_last_image_id = null;
 	_image_window = null;
 
-	constructor() {
+	constructor(doInitialSearch=true) {
 		_last_image_id = 0;
 		base.constructor();
 		_search_options = OurBizSearchOptions();
@@ -1546,18 +1633,18 @@ class ProductsListSearch extends MyListSearchWindow {
 		_search_by_active = create_search_by2("Active");
 		_search_by_description->setonly();
 		_search_by_active->value(1);
-		fill_grid();
+		if(doInitialSearch) delayed_method_call(this, this.fill_grid, null);
 		delayed_method_call(this, this.fill_group_filter, 0);
 	}
 
 	function fill_group_filter(udata)
 	{
 		local tree = group_filter->tree();
-		treeLoadChilds(tree, 0, 0, "product_groups");
+		treeLoadChilds(tree, null, 0, "product_groups");
 		tree->label("----");
 	}
 
-	function get_search_data(data){
+	function get_search_options(){
 		_search_options.search_str = search_str.value();
 		_search_options.description = _search_by_description.value() == 1;
 		_search_options.notes = _search_by_notes.value() == 1;
@@ -1566,16 +1653,15 @@ class ProductsListSearch extends MyListSearchWindow {
 		_search_options.id = _search_by_id.value() == 1;
 		_search_options.active = _search_by_active.value() == 1;
 		_search_options.group_id = group_filter->get_data_at();
-		appServer.products_get_list(grid->_data, _search_options);
+		return _search_options;
 	}
 
-	function get_edit_window(){return getChildWindow("Product Edit", MyEditProductWindow);}
-
-	function cb_btnInsert(sender, udata){
-		this = sender.window();
-		local win = showChildWindow("Product Edit", EditProductWindow);
+	function get_search_data(data, so){
+		appServer.products_get_list(grid->_data, so);
 	}
 
+	function get_edit_window(){return getChildWindow("Product Edit", MyEditProductWindow);}
+
 	function grid_cb(sender, udata){
 		//print("on_row_changed", sender, row);
 		if(sender->why_event() == FLVE_ROW_CHANGED){
@@ -1592,9 +1678,6 @@ class ProductsListSearch extends MyListSearchWindow {
 			}
 		}
 	}
-	function cb_btnUpdate(sender, udata){
-		print_products_list();
-	}
 }
 
 class MyDeliveryCalcWindow extends DeliveryCalcWindow {
@@ -1822,7 +1905,7 @@ class OrdersListSearch extends MyListSearchWindow {
 	_search_by_total = null;
 	_search_wp = null;
 
-	constructor() {
+	constructor(doInitialSearch=true) {
 		base.constructor();
 		label(_tr("Orders List Search"));
 		local cols_info = [
@@ -1843,7 +1926,7 @@ class OrdersListSearch extends MyListSearchWindow {
 		_search_by_total = create_search_by("Total");
 		_search_wp = create_search_by2("WP");
 		_search_by_entities->setonly();
-		fill_grid();
+		if(doInitialSearch) delayed_method_call(this, this.fill_grid, null);
 	}
 
 	function get_data_group_filter(data)
@@ -1851,7 +1934,7 @@ class OrdersListSearch extends MyListSearchWindow {
 		appServer.order_types_list_short(data, 0);
 	}
 
-	function get_search_data(data){
+	function get_search_options(){
 		_search_options.search_str = search_str.value();
 		_search_options.entities = _search_by_entities.value() == 1;
 		_search_options.notes = _search_by_notes.value() == 1;
@@ -1859,15 +1942,15 @@ class OrdersListSearch extends MyListSearchWindow {
 		_search_options.date = _search_by_date.value() == 1;
 		_search_options.total = _search_by_total.value() == 1;
 		_search_options.group_id = group_filter->get_data_at();
-		appServer.orders_get_list(grid->_data, _search_options);
+		return _search_options;
+	}
+
+	function get_search_data(data, so){
+		appServer.orders_get_list(grid->_data, so);
 	}
 
 	function get_edit_window(){return getChildWindow("Order Edit", MyEditOrderWindow);}
 
-	function cb_btnInsert(sender, udata){
-		this = sender.windw();
-		local win = showChildWindow("Order Edit", EditOrderWindow);
-	}
 	function mk_popup()
 	{
 		_popup = create_popup_menu_for(grid, grid->global_style().height());

+ 29 - 19
SquiLu-ourbiz/ourbiz.nut

@@ -984,6 +984,7 @@ class DB_Orders extends DB_Manager {
 	}
 
 	function sql_search_list(qs_tbl, post_tbl){
+		//foreach(k,v in post_tbl) debug_print("\n", k, ":", v)
 		local so = get_search_options(post_tbl);
 		checkQueryStringSAB(qs_tbl, so);
 		local mf = blob();
@@ -1467,8 +1468,8 @@ function dump_group_tree_childs(parent, out_result, parent_map, data_map){
 				//debug_print(myparent, "\t", parent, "\n");
 				if (myparent != parent) break;
 				out_result.write("[");
-				add2sle(out_result, id);
-				add2sle(out_result, myparent);
+				add2sle(out_result, id.tostring());
+				add2sle(out_result, myparent.tostring());
 				add2sle(out_result, data_map[id]);
 				out_result.writen(SLE_SLEEND, 'c');
 				out_result.write("]");
@@ -1488,9 +1489,9 @@ function group_dump_data(db, out_result, tbl){
 	while (stmt.next_row()) {
 		id = stmt.col(0);
 		parent_id = stmt.col(1);
-		if (type(parent_id) == "string") parent_id = 0;
-		//debug_print(parent_id, "\t", id, "\n");
-		parent_map.push([parent_id == SQLite3.Null ? null : parent_id, id]);
+		if (type(parent_id) != "integer") parent_id = 0;
+		//debug_print("\n", parent_id, "\t", id);
+		parent_map.push([parent_id, id]);
 		group_map[id] <- stmt.col(2);
 	}
 	parent_map.sort(@(a,b) a[0] <=> b[0] );
@@ -1504,6 +1505,18 @@ function group_dump_data(db, out_result, tbl){
 	out_result.write("]");
 }
 
+function send_http_error_500(request, err_msg){
+	if(AT_DEV_DBG) {
+		foreach(k,v in get_last_stackinfo()) debug_print("\n", k, ":", v);
+		debug_print("\n", err_msg, "\n")
+	}
+	gmFile.clear();
+	gmFile.write("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: ", err_msg.len(), "\r\n\r\n", err_msg);
+	//debug_print(tostring(gmFile), "\n")
+	request.write_blob(gmFile);
+	return true;
+}
+
 function ourbizDbMobile(request){
 	local data = {};
 	data.page_name = "list_products";
@@ -1569,10 +1582,15 @@ Content-Length: %d
 		}
 
 		if (sql){
-			local stmt = db.prepare(sql);
-			//debug_print(sql, "\n", db.errmsg(), "\n")
-			data = stmt.asSleArray();
-			stmt.finalize();
+			try {
+				local stmt = db.prepare(sql);
+				//debug_print(sql, "\n", db.errmsg(), "\n")
+				data = stmt.asSleArray();
+				stmt.finalize();
+			}
+			catch(e){
+				return send_http_error_500(request, e);
+			}
 		}
 		else if (gmFile.len() > 0){
 			data = gmFile.tostring();
@@ -1719,7 +1737,7 @@ function ourbizDbAction(request){
 		local db = getOurbizDB();
 		local tbl = data.get("__table__", null);
 		local action = data.get("__action__", null);
-		local result, err_msg;
+		local result;
 		//debug_print(tbl, "\n", action, "\n", data.__id__, "\n")
 		gmFile.clear();
 		local db_manager = db_ourbiz_tables.get(tbl, null);
@@ -1727,8 +1745,7 @@ function ourbizDbAction(request){
 			try {
 				result = db_manager.db_action(db, data);
 			} catch(e){
-				err_msg = e;
-				if(AT_DEV_DBG) foreach(k,v in get_last_stackinfo()) debug_print("\n", k, ":", v)
+				return send_http_error_500(request, e);
 			}
 		}
 		if (result != null){
@@ -1744,13 +1761,6 @@ function ourbizDbAction(request){
 			gmFile.write("]]");
 			data = gmFile.tostring();
 		}
-		else if (err_msg) {
-			gmFile.clear();
-			gmFile.write("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: ", err_msg.len(), "\r\n\r\n", err_msg);
-			//debug_print(tostring(gmFile), "\n")
-			request.write_blob(gmFile);
-			return true;
-		}
 		else data = null;
 
 		//debug_print(data, "\n")

+ 4 - 3
SquiLu-ourbiz/search-options.nut

@@ -72,12 +72,13 @@ class OurBizSearchOptions
 		ar.push(url_encode(select_fields));
         }
 	foreach(k,v in OurBizSearchOptions){
-		local ktype = type(v);
+		local val = this[k];
+		local ktype = type(val);
 		if(ktype == "integer") {
-			if(v) ar.push(format("&%s=%d", k, v));
+			if(val) ar.push(format("&%s=%d", k, val));
 		}
 		else if(ktype == "bool"){
-			if(v) ar.push(format("&%s=1", k));
+			if(val) ar.push(format("&%s=1", k));
 		}
 	}
         return ar.concat();