RNA
[blender.git] / source / blender / makesrna / intern / rna_ui.c
index 4ad5273dd5ddca023c8931fe1cdcf4ffb5c26cb5..c46dfe15d8b27f005411ec9cd4b90c2684ed4c86 100644 (file)
 
 #include <stdlib.h>
 
+#include "DNA_screen_types.h"
+
 #include "RNA_define.h"
 #include "RNA_types.h"
 
 #include "rna_internal.h"
 #include "RNA_enum_types.h"
 
+#include "UI_interface.h"
+
+#include "WM_types.h"
+
 #ifdef RNA_RUNTIME
 
 #include "MEM_guardedalloc.h"
 
 #include "RNA_access.h"
 
-#include "DNA_screen_types.h"
-
 #include "BLI_dynstr.h"
 
 #include "BKE_context.h"
 #include "BKE_report.h"
 #include "BKE_screen.h"
 
-#include "UI_interface.h"
-
 #include "WM_api.h"
-#include "WM_types.h"
 
 static ARegionType *region_type_find(ReportList *reports, int space_type, int region_type)
 {
@@ -111,6 +112,22 @@ static void panel_draw(const bContext *C, Panel *pnl)
        RNA_parameter_list_free(list);
 }
 
+static void panel_draw_header(const bContext *C, Panel *pnl)
+{
+       PointerRNA ptr;
+       ParameterList *list;
+       FunctionRNA *func;
+
+       RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->py_srna, pnl, &ptr);
+       func= RNA_struct_find_function(&ptr, "draw_header");
+
+       list= RNA_parameter_list_create(&ptr, func);
+       RNA_parameter_set_lookup(list, "context", &C);
+       pnl->type->py_call(&ptr, func, list);
+
+       RNA_parameter_list_free(list);
+}
+
 static void rna_Panel_unregister(const bContext *C, StructRNA *type)
 {
        ARegionType *art;
@@ -135,7 +152,7 @@ static StructRNA *rna_Panel_register(const bContext *C, ReportList *reports, voi
        PanelType *pt, dummypt = {0};
        Panel dummypanel= {0};
        PointerRNA dummyptr;
-       int have_function[2];
+       int have_function[3];
 
        /* setup dummy panel & panel type to store static properties in */
        dummypanel.type= &dummypt;
@@ -169,6 +186,7 @@ static StructRNA *rna_Panel_register(const bContext *C, ReportList *reports, voi
 
        pt->poll= (have_function[0])? panel_poll: NULL;
        pt->draw= (have_function[1])? panel_draw: NULL;
+       pt->draw_header= (have_function[2])? panel_draw_header: NULL;
 
        BLI_addtail(&art->paneltypes, pt);
 
@@ -182,7 +200,7 @@ static StructRNA *rna_Panel_register(const bContext *C, ReportList *reports, voi
 static StructRNA* rna_Panel_refine(struct PointerRNA *ptr)
 {
        Panel *hdr= (Panel*)ptr->data;
-       return (hdr->type)? hdr->type->py_srna: &RNA_Panel;
+       return (hdr->type && hdr->type->py_srna)? hdr->type->py_srna: &RNA_Panel;
 }
 
 /* Header */
@@ -273,19 +291,260 @@ static StructRNA *rna_Header_register(const bContext *C, ReportList *reports, vo
 static StructRNA* rna_Header_refine(struct PointerRNA *htr)
 {
        Header *hdr= (Header*)htr->data;
-       return (hdr->type)? hdr->type->py_srna: &RNA_Header;
+       return (hdr->type && hdr->type->py_srna)? hdr->type->py_srna: &RNA_Header;
+}
+
+/* Menu */
+
+static int menu_poll(const bContext *C, MenuType *pt)
+{
+       PointerRNA ptr;
+       ParameterList *list;
+       FunctionRNA *func;
+       void *ret;
+       int visible;
+
+       RNA_pointer_create(NULL, pt->py_srna, NULL, &ptr); /* dummy */
+       func= RNA_struct_find_function(&ptr, "poll");
+
+       list= RNA_parameter_list_create(&ptr, func);
+       RNA_parameter_set_lookup(list, "context", &C);
+       pt->py_call(&ptr, func, list);
+
+       RNA_parameter_get_lookup(list, "visible", &ret);
+       visible= *(int*)ret;
+
+       RNA_parameter_list_free(list);
+
+       return visible;
 }
 
-#else
+static void menu_draw(const bContext *C, Menu *hdr)
+{
+       PointerRNA mtr;
+       ParameterList *list;
+       FunctionRNA *func;
+
+       RNA_pointer_create(&CTX_wm_screen(C)->id, hdr->type->py_srna, hdr, &mtr);
+       func= RNA_struct_find_function(&mtr, "draw");
+
+       list= RNA_parameter_list_create(&mtr, func);
+       RNA_parameter_set_lookup(list, "context", &C);
+       hdr->type->py_call(&mtr, func, list);
+
+       RNA_parameter_list_free(list);
+}
+
+static void rna_Menu_unregister(const bContext *C, StructRNA *type)
+{
+       ARegionType *art;
+       MenuType *mt= RNA_struct_blender_type_get(type);
+
+       if(!mt)
+               return;
+       if(!(art=region_type_find(NULL, mt->space_type, RGN_TYPE_HEADER)))
+               return;
+       
+       BLI_freelinkN(&art->menutypes, mt);
+       RNA_struct_free(&BLENDER_RNA, type);
+
+       /* update while blender is running */
+       if(C)
+               WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+}
+
+static StructRNA *rna_Menu_register(const bContext *C, ReportList *reports, void *data, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+       ARegionType *art;
+       MenuType *mt, dummymt = {0};
+       Menu dummymenu= {0};
+       PointerRNA dummymtr;
+       int have_function[2];
+
+       /* setup dummy menu & menu type to store static properties in */
+       dummymenu.type= &dummymt;
+       RNA_pointer_create(NULL, &RNA_Menu, &dummymenu, &dummymtr);
+
+       /* validate the python class */
+       if(validate(&dummymtr, data, have_function) != 0)
+               return NULL;
+       
+       if(!(art=region_type_find(reports, dummymt.space_type, RGN_TYPE_HEADER)))
+               return NULL;
+
+       /* check if we have registered this menu type before, and remove it */
+       for(mt=art->menutypes.first; mt; mt=mt->next) {
+               if(strcmp(mt->idname, dummymt.idname) == 0) {
+                       if(mt->py_srna)
+                               rna_Menu_unregister(C, mt->py_srna);
+                       break;
+               }
+       }
+       
+       /* create a new menu type */
+       mt= MEM_callocN(sizeof(MenuType), "python buttons menu");
+       memcpy(mt, &dummymt, sizeof(dummymt));
+
+       mt->py_srna= RNA_def_struct(&BLENDER_RNA, mt->idname, "Menu"); 
+       mt->py_data= data;
+       mt->py_call= call;
+       mt->py_free= free;
+       RNA_struct_blender_type_set(mt->py_srna, mt);
+
+       mt->poll= (have_function[0])? menu_poll: NULL;
+       mt->draw= (have_function[1])? menu_draw: NULL;
+
+       BLI_addtail(&art->menutypes, mt);
+
+       /* update while blender is running */
+       if(C)
+               WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+       
+       return mt->py_srna;
+}
+
+static StructRNA* rna_Menu_refine(struct PointerRNA *mtr)
+{
+       Menu *hdr= (Menu*)mtr->data;
+       return (hdr->type && hdr->type->py_srna)? hdr->type->py_srna: &RNA_Menu;
+}
+
+static int rna_UILayout_active_get(struct PointerRNA *ptr)
+{
+       return uiLayoutGetActive(ptr->data);
+}
+
+static void rna_UILayout_active_set(struct PointerRNA *ptr, int value)
+{
+       return uiLayoutSetActive(ptr->data, value);
+}
+
+static void rna_UILayout_op_context_set(struct PointerRNA *ptr, int value)
+{
+       return uiLayoutSetOperatorContext(ptr->data, value);
+}
+
+static int rna_UILayout_op_context_get(struct PointerRNA *ptr)
+{
+       return uiLayoutGetOperatorContext(ptr->data);
+}
+
+static int rna_UILayout_enabled_get(struct PointerRNA *ptr)
+{
+       return uiLayoutGetEnabled(ptr->data);
+}
+
+static void rna_UILayout_enabled_set(struct PointerRNA *ptr, int value)
+{
+       return uiLayoutSetEnabled(ptr->data, value);
+}
+
+static int rna_UILayout_red_alert_get(struct PointerRNA *ptr)
+{
+       return uiLayoutGetRedAlert(ptr->data);
+}
+
+static void rna_UILayout_red_alert_set(struct PointerRNA *ptr, int value)
+{
+       return uiLayoutSetRedAlert(ptr->data, value);
+}
+
+static int rna_UILayout_keep_aspect_get(struct PointerRNA *ptr)
+{
+       return uiLayoutGetKeepAspect(ptr->data);
+}
+
+static void rna_UILayout_keep_aspect_set(struct PointerRNA *ptr, int value)
+{
+       return uiLayoutSetKeepAspect(ptr->data, value);
+}
+
+static int rna_UILayout_alignment_get(struct PointerRNA *ptr)
+{
+       return uiLayoutGetAlignment(ptr->data);
+}
+
+static void rna_UILayout_alignment_set(struct PointerRNA *ptr, int value)
+{
+       return uiLayoutSetAlignment(ptr->data, value);
+}
+
+static float rna_UILayout_scale_x_get(struct PointerRNA *ptr)
+{
+       return uiLayoutGetScaleX(ptr->data);
+}
+
+static void rna_UILayout_scale_x_set(struct PointerRNA *ptr, float value)
+{
+       return uiLayoutSetScaleX(ptr->data, value);
+}
+
+static float rna_UILayout_scale_y_get(struct PointerRNA *ptr)
+{
+       return uiLayoutGetScaleY(ptr->data);
+}
+
+static void rna_UILayout_scale_y_set(struct PointerRNA *ptr, float value)
+{
+       return uiLayoutSetScaleY(ptr->data, value);
+}
+
+#else // RNA_RUNTIME
 
 static void rna_def_ui_layout(BlenderRNA *brna)
 {
        StructRNA *srna;
+       PropertyRNA *prop;
+
+       static EnumPropertyItem alignment_items[] = {
+               {UI_LAYOUT_ALIGN_EXPAND, "EXPAND", 0, "Expand", ""},
+               {UI_LAYOUT_ALIGN_LEFT, "LEFT", 0, "Left", ""},
+               {UI_LAYOUT_ALIGN_CENTER, "CENTER", 0, "Center", ""},
+               {UI_LAYOUT_ALIGN_RIGHT, "RIGHT", 0, "RIght", ""},
+               {0, NULL, 0, NULL, NULL}};
+               
+       /* see WM_types.h */
+       static EnumPropertyItem operator_context_items[] = {
+               {WM_OP_INVOKE_DEFAULT, "INVOKE_DEFAULT", 0, "Invoke Default", ""},
+               {WM_OP_INVOKE_REGION_WIN, "INVOKE_REGION_WIN", 0, "Invoke Region Window", ""},
+               {WM_OP_INVOKE_AREA, "INVOKE_AREA", 0, "Invoke Area", ""},
+               {WM_OP_INVOKE_SCREEN, "INVOKE_SCREEN", 0, "Invoke Screen", ""},
+               {WM_OP_EXEC_DEFAULT, "EXEC_DEFAULT", 0, "Exec Default", ""},
+               {WM_OP_EXEC_REGION_WIN, "EXEC_REGION_WIN", 0, "Exec Region Window", ""},
+               {WM_OP_EXEC_AREA, "EXEC_AREA", 0, "Exec Area", ""},
+               {WM_OP_EXEC_SCREEN, "EXEC_SCREEN", 0, "Exec Screen", ""},
+               {0, NULL, 0, NULL, NULL}};
 
        srna= RNA_def_struct(brna, "UILayout", NULL);
        RNA_def_struct_sdna(srna, "uiLayout");
        RNA_def_struct_ui_text(srna, "UI Layout", "User interface layout in a panel or header.");
 
+       prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_funcs(prop, "rna_UILayout_active_get", "rna_UILayout_active_set");
+       
+       prop= RNA_def_property(srna, "operator_context", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, operator_context_items);
+       RNA_def_property_enum_funcs(prop, "rna_UILayout_op_context_get", "rna_UILayout_op_context_set", NULL);
+
+       prop= RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_funcs(prop, "rna_UILayout_enabled_get", "rna_UILayout_enabled_set");
+
+       prop= RNA_def_property(srna, "red_alert", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_funcs(prop, "rna_UILayout_red_alert_get", "rna_UILayout_red_alert_set");
+
+       prop= RNA_def_property(srna, "alignment", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, alignment_items);
+       RNA_def_property_enum_funcs(prop, "rna_UILayout_alignment_get", "rna_UILayout_alignment_set", NULL);
+
+       prop= RNA_def_property(srna, "keep_aspect", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_funcs(prop, "rna_UILayout_keep_aspect_get", "rna_UILayout_keep_aspect_set");
+
+       prop= RNA_def_property(srna, "scale_x", PROP_FLOAT, PROP_UNSIGNED);
+       RNA_def_property_float_funcs(prop, "rna_UILayout_scale_x_get", "rna_UILayout_scale_x_set", NULL);
+
+       prop= RNA_def_property(srna, "scale_y", PROP_FLOAT, PROP_UNSIGNED);
+       RNA_def_property_float_funcs(prop, "rna_UILayout_scale_y_get", "rna_UILayout_scale_y_set", NULL);
+
        RNA_api_ui_layout(srna);
 }
 
@@ -314,6 +573,11 @@ static void rna_def_panel(BlenderRNA *brna)
        RNA_def_function_flag(func, FUNC_REGISTER);
        RNA_def_pointer(func, "context", "Context", "", "");
 
+       func= RNA_def_function(srna, "draw_header", NULL);
+       RNA_def_function_ui_description(func, "Draw buttons into the panel header UI layout.");
+       RNA_def_function_flag(func, FUNC_REGISTER);
+       RNA_def_pointer(func, "context", "Context", "", "");
+
        prop= RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
        RNA_def_property_struct_type(prop, "UILayout");
 
@@ -373,12 +637,56 @@ static void rna_def_header(BlenderRNA *brna)
        RNA_def_property_flag(prop, PROP_REGISTER);
 }
 
+static void rna_def_menu(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+       FunctionRNA *func;
+       
+       srna= RNA_def_struct(brna, "Menu", NULL);
+       RNA_def_struct_ui_text(srna, "Menu", "Editor menu containing buttons.");
+       RNA_def_struct_sdna(srna, "Menu");
+       RNA_def_struct_refine_func(srna, "rna_Menu_refine");
+       RNA_def_struct_register_funcs(srna, "rna_Menu_register", "rna_Menu_unregister");
+
+       /* poll */
+       func= RNA_def_function(srna, "poll", NULL);
+       RNA_def_function_ui_description(func, "Test if the menu is visible or not.");
+       RNA_def_function_flag(func, FUNC_REGISTER|FUNC_REGISTER_OPTIONAL);
+       RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
+       RNA_def_pointer(func, "context", "Context", "", "");
+
+       /* draw */
+       func= RNA_def_function(srna, "draw", NULL);
+       RNA_def_function_ui_description(func, "Draw buttons into the menu UI layout.");
+       RNA_def_function_flag(func, FUNC_REGISTER);
+       RNA_def_pointer(func, "context", "Context", "", "");
+
+       prop= RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "UILayout");
+
+       /* registration */
+       prop= RNA_def_property(srna, "idname", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "type->idname");
+       RNA_def_property_flag(prop, PROP_REGISTER);
+
+       prop= RNA_def_property(srna, "label", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "type->label");
+       RNA_def_property_flag(prop, PROP_REGISTER);
+
+       prop= RNA_def_property(srna, "space_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
+       RNA_def_property_enum_items(prop, space_type_items);
+       RNA_def_property_flag(prop, PROP_REGISTER);
+}
+
 void RNA_def_ui(BlenderRNA *brna)
 {
        rna_def_ui_layout(brna);
        rna_def_panel(brna);
        rna_def_header(brna);
+       rna_def_menu(brna);
 }
 
-#endif
+#endif // RNA_RUNTIME