Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2009-03-13 16:38:41 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2009-03-13 16:38:41 +0300
commit4c3d64116e2c74315afea7b005ffaf320178337f (patch)
tree86d6db3a35fd5847387c2970ba0d160d9f92b0a7 /source/blender/editors/interface
parenta4793a3b4ac298a651f7bab0bafd809287647509 (diff)
2.5: UI Layout Engine, initial code.
* As a test, used by: * Object buttons, tried to make it match the mockup. * Text window header. * Text window properties panel. * Panel interaction with view2d is still problematic, need to make this work properly still. * Templates are very basic, the ones there are simple but already can follow the object buttons mockup quite closely. * It's based on a three level system: panels, templates and items. To get an idea of what that means in practice, see: http://wiki.blender.org/index.php/BlenderDev/Blender2.5/UI_LayoutEngine#Panels.2C_Templates_and_Items
Diffstat (limited to 'source/blender/editors/interface')
-rw-r--r--source/blender/editors/interface/interface_draw.c4
-rw-r--r--source/blender/editors/interface/interface_handlers.c3
-rw-r--r--source/blender/editors/interface/interface_layout.c943
-rw-r--r--source/blender/editors/interface/interface_panel.c3
-rw-r--r--source/blender/editors/interface/interface_utils.c57
-rw-r--r--source/blender/editors/interface/view2d.c21
6 files changed, 1004 insertions, 27 deletions
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 8c090227737..f93c4aa759a 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -2221,8 +2221,8 @@ static void ui_draw_text(uiBut *but, float x, float y, int sunken)
/* text color, with pulldown item exception */
if(but->dt==UI_EMBOSSP) {
if (sunken) {
- float col[4];
- UI_GetThemeColor4ubv(TH_MENU_TEXT, col);
+ float col[3];
+ UI_GetThemeColor3fv(TH_MENU_TEXT, col);
if ((col[0] + col[1] + col[2]) / 3.f < 0.5f)
UI_ThemeColorShadeAlpha(TH_HEADER, 20, alpha_offs);
} else if((but->flag & UI_ACTIVE) && but->type!=LABEL) { // LABEL = title in pulldowns
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index e4a5ddf75fa..9d679f64378 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -2961,6 +2961,8 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
data->state= state;
+ ui_check_but(but);
+
/* redraw */
ED_region_tag_redraw(data->region);
}
@@ -3050,6 +3052,7 @@ static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *b
MEM_freeN(but->active);
but->active= NULL;
but->flag &= ~(UI_ACTIVE|UI_SELECT);
+ ui_check_but(but);
/* adds empty mousemove in queue for re-init handler, in case mouse is
* still over a button. we cannot just check for this ourselfs because
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
new file mode 100644
index 00000000000..42f656c46a0
--- /dev/null
+++ b/source/blender/editors/interface/interface_layout.c
@@ -0,0 +1,943 @@
+
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_listbase.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_idprop.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_util.h"
+#include "ED_types.h"
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/************************ Structs and Defines *************************/
+
+#define COLUMN_SPACE 5
+#define TEMPLATE_SPACE 5
+#define STACK_SPACE 5
+#define BUTTON_SPACE_X 5
+#define BUTTON_SPACE_Y 2
+
+#define RNA_NO_INDEX -1
+
+/* Item */
+
+typedef enum uiItemType {
+ ITEM_OPERATOR,
+ ITEM_RNA_PROPERTY,
+ ITEM_MENU,
+ ITEM_LABEL
+} uiItemType;
+
+enum uiItemFlag {
+ ITEM_ICON,
+ ITEM_TEXT
+};
+
+typedef struct uiItem {
+ struct uiItem *next, *prev;
+ uiItemType type;
+ int slot;
+
+ const char *name;
+ int icon;
+} uiItem;
+
+typedef struct uiItemRNA {
+ uiItem item;
+
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+} uiItemRNA;
+
+typedef struct uiItemOp {
+ uiItem item;
+
+ wmOperatorType *ot;
+ IDProperty *properties;
+ int context;
+} uiItemOp;
+
+typedef struct uiItemLMenu {
+ uiItem item;
+
+ uiMenuCreateFunc func;
+} uiItemLMenu;
+
+/* Template */
+
+typedef enum uiTemplateType {
+ TEMPLATE_COLUMN,
+ TEMPLATE_LR,
+ TEMPLATE_STACK,
+
+ TEMPLATE_HEADER_MENUS,
+ TEMPLATE_HEADER_BUTTONS,
+ TEMPLATE_HEADER_ID
+} uiTemplateType;
+
+typedef struct uiTemplate {
+ struct uiTemplate *next, *prev;
+ uiTemplateType type;
+
+ ListBase items;
+ int color;
+} uiTemplate;
+
+typedef struct uiTemplateStck {
+ uiTemplate template;
+ uiLayout *sublayout;
+} uiTemplateStck;
+
+typedef struct uiTemplateHeadID {
+ uiTemplate template;
+
+ PointerRNA ptr;
+ char *propname;
+ int flag;
+ uiIDPoinFunc func;
+} uiTemplateHeadID;
+
+/* Layout */
+
+struct uiLayout {
+ ListBase templates;
+ int opcontext;
+ int dir;
+ int x, y, w, h;
+};
+
+void ui_layout_free(uiLayout *layout);
+void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y);
+
+/************************** Item ***************************/
+
+static int ui_item_fit(int item, int all, int available)
+{
+ if(all > available)
+ return (item*available)/all;
+
+ return all;
+}
+
+/* create buttons for an item with an RNA array */
+static void ui_item_array(uiBlock *block, uiItemRNA *rnaitem, int len, int x, int y, int w, int h)
+{
+ PropertyType type;
+ PropertySubType subtype;
+ char *name;
+ int a;
+
+ /* retrieve type and subtype */
+ type= RNA_property_type(&rnaitem->ptr, rnaitem->prop);
+ subtype= RNA_property_subtype(&rnaitem->ptr, rnaitem->prop);
+
+ /* create label */
+ if(rnaitem->item.name)
+ name= (char*)rnaitem->item.name;
+ else
+ name= (char*)RNA_property_ui_name(&rnaitem->ptr, rnaitem->prop);
+
+ uiDefBut(block, LABEL, 0, name, x, y + h - YIC, w, YIC, NULL, 0.0, 0.0, 0, 0, "");
+
+ /* create buttons */
+ uiBlockBeginAlign(block);
+
+ if(type == PROP_BOOLEAN && len == 20) {
+ /* special check for layer layout */
+ int butw, buth;
+
+ butw= ui_item_fit(XIC, XIC*10 + BUTTON_SPACE_X, w);
+ buth= MIN2(YIC, butw);
+
+ y += 2*(YIC - buth);
+
+ uiBlockBeginAlign(block);
+ for(a=0; a<5; a++)
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
+ for(a=0; a<5; a++)
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a+10, "", ICON_BLANK1, x + butw*a, y, butw, buth);
+ uiBlockEndAlign(block);
+
+ x += 5*butw + BUTTON_SPACE_X;
+
+ uiBlockBeginAlign(block);
+ for(a=0; a<5; a++)
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a+5, "", ICON_BLANK1, x + butw*a, y+buth, butw, buth);
+ for(a=0; a<5; a++)
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a+15, "", ICON_BLANK1, x + butw*a, y, butw, buth);
+ uiBlockEndAlign(block);
+ }
+ else if(subtype == PROP_MATRIX) {
+ /* matrix layout */
+ int row, col;
+
+ len= ceil(sqrt(len));
+
+ h /= len;
+ w /= len;
+
+ // XXX test
+ for(a=0; a<len; a++) {
+ col= a%len;
+ row= a/len;
+
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, "", 0, x + w*col, y+(row-a-1)*YIC, w, YIC);
+ }
+ }
+ else if(len <= 4 && ELEM3(subtype, PROP_ROTATION, PROP_VECTOR, PROP_COLOR)) {
+ /* layout for known array subtypes */
+ static char *vectoritem[4]= {"X:", "Y:", "Z:", "W:"};
+ static char *quatitem[4]= {"W:", "X:", "Y:", "Z:"};
+ static char *coloritem[4]= {"R:", "G:", "B:", "A:"};
+
+ for(a=0; a<len; a++) {
+ if(len == 4 && subtype == PROP_ROTATION)
+ name= quatitem[a];
+ else if(subtype == PROP_VECTOR || subtype == PROP_ROTATION)
+ name= vectoritem[a];
+ else
+ name= coloritem[a];
+
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, name, 0, x, y+(len-a-1)*YIC, w, YIC);
+ }
+ }
+ else {
+ /* default array layout */
+ for(a=0; a<len; a++)
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, a, "", 0, x, y+(len-a-1)*YIC, w, YIC);
+ }
+
+ uiBlockEndAlign(block);
+}
+
+/* create lable + button for RNA property */
+static void ui_item_with_label(uiBlock *block, uiItemRNA *rnaitem, int x, int y, int w, int h)
+{
+ char *name;
+ int butw;
+
+ if(rnaitem->item.name)
+ name= (char*)rnaitem->item.name;
+ else
+ name= (char*)RNA_property_ui_name(&rnaitem->ptr, rnaitem->prop);
+
+ if(strcmp(name, "") != 0) {
+ butw= GetButStringLength(name);
+ uiDefBut(block, LABEL, 0, name, x, y, butw, h, NULL, 0.0, 0.0, 0, 0, "");
+
+ x += butw;
+ w -= butw;
+ }
+
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, rnaitem->index, "", rnaitem->item.icon, x, y, w, h);
+}
+
+/* create buttons for an arbitrary item */
+static void ui_item_buts(uiBlock *block, uiItem *item, int x, int y, int w, int h)
+{
+ if(item->type == ITEM_RNA_PROPERTY) {
+ /* RNA property */
+ uiItemRNA *rnaitem= (uiItemRNA*)item;
+ PropertyType type;
+ int len;
+
+ /* retrieve info */
+ type= RNA_property_type(&rnaitem->ptr, rnaitem->prop);
+ len= RNA_property_array_length(&rnaitem->ptr, rnaitem->prop);
+
+ /* array property */
+ if(rnaitem->index == RNA_NO_INDEX && len > 0)
+ ui_item_array(block, rnaitem, len, x, y, w, h);
+ /* property with separate label */
+ else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER)
+ ui_item_with_label(block, rnaitem, x, y, w, h);
+ /* single button */
+ else
+ uiDefAutoButR(block, &rnaitem->ptr, rnaitem->prop, rnaitem->index, (char*)item->name, item->icon, x, y, w, h);
+ }
+ else if(item->type == ITEM_OPERATOR) {
+ /* operator */
+ uiItemOp *opitem= (uiItemOp*)item;
+
+ if(item->icon && item->name)
+ uiDefIconTextButO(block, BUT, opitem->ot->idname, opitem->context, item->icon, (char*)item->name, x, y, w, h, NULL);
+ else if(item->icon)
+ uiDefIconButO(block, BUT, opitem->ot->idname, opitem->context, item->icon, x, y, w, h, NULL);
+ /* text only */
+ else
+ uiDefButO(block, BUT, opitem->ot->idname, opitem->context, (char*)item->name, x, y, w, h, NULL);
+ }
+ else if(item->type == ITEM_MENU) {
+ /* menu */
+ uiItemLMenu *menuitem= (uiItemLMenu*)item;
+
+ uiDefMenuBut(block, menuitem->func, NULL, (char*)item->name, x, y-2, w-3, h+4, "");
+ }
+ else if(item->type == ITEM_LABEL) {
+ /* label */
+
+ if(item->icon && item->name)
+ uiDefIconTextBut(block, LABEL, 0, item->icon, (char*)item->name, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
+ else if(item->icon)
+ uiDefIconBut(block, LABEL, 0, item->icon, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
+ else if((char*)item->name)
+ uiDefBut(block, LABEL, 0, (char*)item->name, x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
+ }
+ else {
+ /* separator */
+ uiDefBut(block, SEPR, 0, "", x, y, w, h, NULL, 0.0, 0.0, 0, 0, "");
+ }
+}
+
+/* estimated size of text + icon */
+static int ui_text_icon_width(const char *name, int icon)
+{
+ if(icon && name && strcmp(name, "") == 0)
+ return XIC; /* icon only */
+ else if(icon && name)
+ return XIC + GetButStringLength((char*)name); /* icon + text */
+ else if(name)
+ return GetButStringLength((char*)name); /* text only */
+ else
+ return 0;
+}
+
+/* estimated size of an item */
+static void ui_item_size(uiItem *item, int *r_w, int *r_h)
+{
+ const char *name;
+ int w, h;
+
+ if(item->type == ITEM_RNA_PROPERTY) {
+ /* RNA property */
+ uiItemRNA *rnaitem= (uiItemRNA*)item;
+ PropertyType type;
+ PropertySubType subtype;
+ int len;
+
+ name= item->name;
+ if(!name)
+ name= RNA_property_ui_name(&rnaitem->ptr, rnaitem->prop);
+
+ w= ui_text_icon_width(name, item->icon);
+ h= YIC;
+
+ /* arbitrary extended width by type */
+ type= RNA_property_type(&rnaitem->ptr, rnaitem->prop);
+ subtype= RNA_property_subtype(&rnaitem->ptr, rnaitem->prop);
+ len= RNA_property_array_length(&rnaitem->ptr, rnaitem->prop);
+
+ if(type == PROP_BOOLEAN && !item->icon)
+ w += XIC;
+ else if(type == PROP_INT || type == PROP_FLOAT)
+ w += 2*XIC;
+ else if(type == PROP_STRING)
+ w += 8*XIC;
+
+ /* increase height for arrays */
+ if(rnaitem->index == RNA_NO_INDEX && len > 0) {
+ if(name && strcmp(name, "") == 0 && item->icon == 0)
+ h= 0;
+
+ if(type == PROP_BOOLEAN && len == 20)
+ h += 2*YIC;
+ else if(subtype == PROP_MATRIX)
+ h += ceil(sqrt(len))*YIC;
+ else
+ h += len*YIC;
+ }
+ }
+ else if(item->type == ITEM_OPERATOR) {
+ /* operator */
+ uiItemOp *opitem= (uiItemOp*)item;
+
+ name= item->name;
+ if(!name)
+ name= opitem->ot->name;
+
+ w= ui_text_icon_width(name, item->icon);
+ h= YIC;
+ }
+ else {
+ /* other */
+ w= ui_text_icon_width(item->name, item->icon);
+ h= YIC;
+ }
+
+ if(r_w) *r_w= w;
+ if(r_h) *r_h= h;
+}
+
+static void ui_item_free(uiItem *item)
+{
+ if(item->type == ITEM_OPERATOR) {
+ uiItemOp *opitem= (uiItemOp*)item;
+
+ if(opitem->properties) {
+ IDP_FreeProperty(opitem->properties);
+ MEM_freeN(opitem->properties);
+ }
+ }
+}
+
+/* operator items */
+void uiItemFullO(uiLayout *layout, int slot, const char *name, int icon, char *idname, IDProperty *properties, int context)
+{
+ uiTemplate *template= layout->templates.last;
+ wmOperatorType *ot= WM_operatortype_find(idname);
+ uiItemOp *opitem;
+
+ if(!ot)
+ return;
+
+ opitem= MEM_callocN(sizeof(uiItemOp), "uiItemOp");
+
+ opitem->item.name= name;
+ opitem->item.icon= icon;
+ opitem->item.type= ITEM_OPERATOR;
+ opitem->item.slot= slot;
+
+ opitem->ot= ot;
+ opitem->properties= properties;
+ opitem->context= context;
+
+ BLI_addtail(&template->items, opitem);
+}
+
+void uiItemEnumO(uiLayout *layout, int slot, const char *name, int icon, char *opname, char *propname, int value)
+{
+ PointerRNA ptr;
+
+ WM_operator_properties_create(&ptr, opname);
+ RNA_enum_set(&ptr, propname, value);
+
+ uiItemFullO(layout, slot, name, icon, opname, ptr.data, layout->opcontext);
+}
+
+void uiItemsEnumO(uiLayout *layout, int slot, char *opname, char *propname)
+{
+ wmOperatorType *ot= WM_operatortype_find(opname);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ if(!ot || !ot->srna)
+ return;
+
+ RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
+ prop= RNA_struct_find_property(&ptr, propname);
+
+ if(prop && RNA_property_type(&ptr, prop) == PROP_ENUM) {
+ const EnumPropertyItem *item;
+ int totitem, i;
+
+ RNA_property_enum_items(&ptr, prop, &item, &totitem);
+
+ for(i=0; i<totitem; i++)
+ uiItemEnumO(layout, slot, "", 0, opname, propname, item[i].value);
+ }
+}
+
+void uiItemBooleanO(uiLayout *layout, int slot, const char *name, int icon, char *opname, char *propname, int value)
+{
+ PointerRNA ptr;
+
+ WM_operator_properties_create(&ptr, opname);
+ RNA_boolean_set(&ptr, propname, value);
+
+ uiItemFullO(layout, slot, name, icon, opname, ptr.data, layout->opcontext);
+}
+
+void uiItemIntO(uiLayout *layout, int slot, const char *name, int icon, char *opname, char *propname, int value)
+{
+ PointerRNA ptr;
+
+ WM_operator_properties_create(&ptr, opname);
+ RNA_int_set(&ptr, propname, value);
+
+ uiItemFullO(layout, slot, name, icon, opname, ptr.data, layout->opcontext);
+}
+
+void uiItemFloatO(uiLayout *layout, int slot, const char *name, int icon, char *opname, char *propname, float value)
+{
+ PointerRNA ptr;
+
+ WM_operator_properties_create(&ptr, opname);
+ RNA_float_set(&ptr, propname, value);
+
+ uiItemFullO(layout, slot, name, icon, opname, ptr.data, layout->opcontext);
+}
+
+void uiItemStringO(uiLayout *layout, int slot, const char *name, int icon, char *opname, char *propname, char *value)
+{
+ PointerRNA ptr;
+
+ WM_operator_properties_create(&ptr, opname);
+ RNA_string_set(&ptr, propname, value);
+
+ uiItemFullO(layout, slot, name, icon, opname, ptr.data, layout->opcontext);
+}
+
+void uiItemO(uiLayout *layout, int slot, const char *name, int icon, char *opname)
+{
+ uiItemFullO(layout, slot, name, icon, opname, NULL, layout->opcontext);
+}
+
+/* RNA property items */
+void uiItemFullR(uiLayout *layout, int slot, const char *name, int icon, PointerRNA *ptr, char *propname, int index)
+{
+ uiTemplate *template= layout->templates.last;
+ PropertyRNA *prop;
+ uiItemRNA *rnaitem;
+
+ prop= RNA_struct_find_property(ptr, propname);
+ if(!prop)
+ return;
+
+ rnaitem= MEM_callocN(sizeof(uiItemRNA), "uiItemRNA");
+
+ rnaitem->item.name= name;
+ rnaitem->item.icon= icon;
+ rnaitem->item.type= ITEM_RNA_PROPERTY;
+ rnaitem->item.slot= slot;
+
+ rnaitem->ptr= *ptr;
+ rnaitem->prop= prop;
+ rnaitem->index= index;
+
+ BLI_addtail(&template->items, rnaitem);
+}
+
+void uiItemR(uiLayout *layout, int slot, const char *name, int icon, PointerRNA *ptr, char *propname)
+{
+ uiItemFullR(layout, slot, name, icon, ptr, propname, RNA_NO_INDEX);
+}
+
+/* menu item */
+void uiItemMenu(uiLayout *layout, int slot, const char *name, int icon, uiMenuCreateFunc func)
+{
+ uiTemplate *template= layout->templates.last;
+ uiItemLMenu *menuitem= MEM_callocN(sizeof(uiItemLMenu), "uiItemLMenu");
+
+ menuitem->item.name= name;
+ menuitem->item.icon= icon;
+ menuitem->item.type= ITEM_MENU;
+ menuitem->item.slot= slot;
+
+ menuitem->func= func;
+
+ BLI_addtail(&template->items, menuitem);
+}
+
+/* label item */
+void uiItemLabel(uiLayout *layout, int slot, const char *name, int icon)
+{
+ uiTemplate *template= layout->templates.last;
+ uiItem *item= MEM_callocN(sizeof(uiItem), "uiItem");
+
+ item->name= name;
+ item->icon= icon;
+ item->type= ITEM_LABEL;
+ item->slot= slot;
+
+ BLI_addtail(&template->items, item);
+}
+
+/**************************** Template ***************************/
+
+/* multi-column layout */
+static void ui_layout_column(uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
+{
+ uiItem *item;
+ int col, totcol= 0, colx, coly, colw, miny, itemw, itemh;
+
+ /* compute number of columns */
+ for(item=template->items.first; item; item=item->next)
+ totcol= MAX2(item->slot+1, totcol);
+
+ if(totcol == 0)
+ return;
+
+ colx= *x;
+ colw= (w - (totcol-1)*COLUMN_SPACE)/totcol;
+ miny= *y;
+
+ /* create column per column */
+ for(col=0; col<totcol; col++) {
+ coly= *y;
+
+ for(item=template->items.first; item; item=item->next) {
+ if(item->slot != col)
+ continue;
+
+ ui_item_size(item, &itemw, &itemh);
+
+ coly -= itemh + BUTTON_SPACE_Y;
+ ui_item_buts(block, item, colx, coly, colw, itemh);
+ }
+
+ colx += colw + COLUMN_SPACE;
+ miny= MIN2(miny, coly);
+ }
+
+ *y= miny;
+}
+
+/* left-right layout, with buttons aligned on both sides */
+static void ui_layout_lr(uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
+{
+ uiItem *item;
+ int totw= 0, maxh= 0, itemw, itemh, leftx, rightx;
+
+ /* estimate total width of buttons */
+ for(item=template->items.first; item; item=item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ totw += itemw;
+ maxh= MAX2(maxh, itemh);
+ }
+
+ if(totw == 0)
+ return;
+
+ /* create buttons starting from left and right */
+ leftx= *x;
+ rightx= *x + w;
+
+ for(item=template->items.first; item; item=item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ itemw= ui_item_fit(itemw, totw+BUTTON_SPACE_X, w);
+
+ if(item->slot == UI_TSLOT_LR_LEFT) {
+ ui_item_buts(block, item, leftx, *y-itemh, itemw, itemh);
+ leftx += itemw;
+ }
+ else {
+ rightx -= itemw;
+ ui_item_buts(block, item, rightx, *y-itemh, itemw, itemh);
+ }
+ }
+
+ *y -= maxh;
+}
+
+/* element in a stack layout */
+static void ui_layout_stack(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
+{
+ uiTemplateStck *stack= (uiTemplateStck*)template;
+ int starty, startx;
+
+ startx= *x;
+ starty= *y;
+
+ /* some extra padding */
+ stack->sublayout->x= *x + STACK_SPACE;
+ stack->sublayout->w= w - 2*STACK_SPACE;
+ stack->sublayout->y= *y - STACK_SPACE;
+ stack->sublayout->h= h;
+
+ /* do layout for elements in sublayout */
+ ui_layout_end(C, block, stack->sublayout, NULL, y);
+
+ /* roundbox around the sublayout */
+ uiDefBut(block, ROUNDBOX, 0, "", startx, *y, w, starty - *y, NULL, 7.0, 0.0, 3, 20, "");
+}
+
+static void ui_layout_header_buttons(uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
+{
+ uiItem *item;
+ int itemw, itemh;
+
+ uiBlockBeginAlign(block);
+
+ for(item=template->items.first; item; item=item->next) {
+ ui_item_size(item, &itemw, &itemh);
+ ui_item_buts(block, item, *x, *y, itemw, itemh);
+ *x += itemw;
+ }
+
+ uiBlockEndAlign(block);
+}
+
+static void ui_layout_header_menus(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
+{
+ ScrArea *sa= CTX_wm_area(C);
+
+ *x= ED_area_header_standardbuttons(C, block, *y);
+
+ if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ uiBlockSetEmboss(block, UI_EMBOSSP);
+ ui_layout_header_buttons(layout, block, template, x, y, w, h);
+ }
+
+ uiBlockSetEmboss(block, UI_EMBOSS);
+}
+
+static void ui_layout_header_id(const bContext *C, uiLayout *layout, uiBlock *block, uiTemplate *template, int *x, int *y, int w, int h)
+{
+ uiTemplateHeadID *idtemplate= (uiTemplateHeadID*)template;
+ PointerRNA idptr;
+
+ idptr= RNA_pointer_get(&idtemplate->ptr, idtemplate->propname);
+
+ *x= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)idptr.data, ID_TXT, NULL, *x, *y,
+ idtemplate->func, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE);
+}
+
+void ui_template_free(uiTemplate *template)
+{
+ uiItem *item;
+
+ if(template->type == TEMPLATE_STACK) {
+ uiTemplateStck *stack= (uiTemplateStck*)template;
+ ui_layout_free(stack->sublayout);
+ }
+
+ for(item=template->items.first; item; item=item->next)
+ ui_item_free(item);
+
+ BLI_freelistN(&template->items);
+}
+
+/* template create functions */
+void uiTemplateColumn(uiLayout *layout)
+{
+ uiTemplate *template;
+
+ template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
+ template->type= TEMPLATE_COLUMN;
+
+ BLI_addtail(&layout->templates, template);
+}
+
+
+void uiTemplateLeftRight(uiLayout *layout)
+{
+ uiTemplate *template;
+
+ template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
+ template->type= TEMPLATE_LR;
+
+ BLI_addtail(&layout->templates, template);
+}
+
+uiLayout *uiTemplateStack(uiLayout *layout)
+{
+ uiTemplateStck *stack;
+
+ stack= MEM_callocN(sizeof(uiTemplateStck), "uiTemplateStck");
+ stack->template.type= TEMPLATE_STACK;
+ stack->sublayout= uiLayoutBegin(layout->dir, 0, 0, 0, 0);
+ BLI_addtail(&layout->templates, stack);
+
+ return stack->sublayout;
+}
+
+void uiTemplateHeaderMenus(uiLayout *layout)
+{
+ uiTemplate *template;
+
+ template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
+ template->type= TEMPLATE_HEADER_MENUS;
+
+ BLI_addtail(&layout->templates, template);
+}
+
+void uiTemplateHeaderButtons(uiLayout *layout)
+{
+ uiTemplate *template;
+
+ template= MEM_callocN(sizeof(uiTemplate), "uiTemplate");
+ template->type= TEMPLATE_HEADER_BUTTONS;
+
+ BLI_addtail(&layout->templates, template);
+}
+
+void uiTemplateHeaderID(uiLayout *layout, PointerRNA *ptr, char *propname, int flag, uiIDPoinFunc func)
+{
+ uiTemplateHeadID *idtemplate;
+
+ idtemplate= MEM_callocN(sizeof(uiTemplateHeadID), "uiTemplateHeadID");
+ idtemplate->template.type= TEMPLATE_HEADER_ID;
+ idtemplate->ptr= *ptr;
+ idtemplate->propname= propname;
+ idtemplate->flag= flag;
+ idtemplate->func= func;
+
+ BLI_addtail(&layout->templates, idtemplate);
+}
+
+void uiTemplateSetColor(uiLayout *layout, int color)
+{
+ uiTemplate *template= layout->templates.last;
+
+ template->color= color;
+}
+
+/********************** Layout *******************/
+
+static void ui_layout_templates(const bContext *C, uiBlock *block, uiLayout *layout)
+{
+ uiTemplate *template;
+ int oldcolor= 0;
+
+ for(template=layout->templates.first; template; template=template->next) {
+ if(template->color) {
+ oldcolor= uiBlockGetCol(block);
+ uiBlockSetCol(block, template->color);
+ }
+
+ switch(template->type) {
+ case TEMPLATE_COLUMN:
+ ui_layout_column(layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+ break;
+ case TEMPLATE_LR:
+ ui_layout_lr(layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+ break;
+ case TEMPLATE_STACK:
+ ui_layout_stack(C, layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+ break;
+ case TEMPLATE_HEADER_MENUS:
+ ui_layout_header_menus(C, layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+ break;
+ case TEMPLATE_HEADER_BUTTONS:
+ ui_layout_header_buttons(layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+ break;
+ case TEMPLATE_HEADER_ID:
+ ui_layout_header_id(C, layout, block, template, &layout->x, &layout->y, layout->w, layout->h);
+ break;
+ }
+
+ if(template->color)
+ uiBlockSetCol(block, oldcolor);
+
+ if(layout->dir == UI_LAYOUT_HORIZONTAL)
+ layout->x += TEMPLATE_SPACE;
+ else
+ layout->y -= TEMPLATE_SPACE;
+ }
+}
+
+void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
+{
+ ui_layout_templates(C, block, layout);
+
+ if(x) *x= layout->x;
+ if(y) *y= layout->y;
+}
+
+void ui_layout_free(uiLayout *layout)
+{
+ uiTemplate *template;
+
+ for(template=layout->templates.first; template; template=template->next)
+ ui_template_free(template);
+
+ BLI_freelistN(&layout->templates);
+ MEM_freeN(layout);
+}
+
+uiLayout *uiLayoutBegin(int dir, int x, int y, int w, int h)
+{
+ uiLayout *layout;
+
+ layout= MEM_callocN(sizeof(uiLayout), "uiLayout");
+ layout->opcontext= WM_OP_INVOKE_REGION_WIN;
+ layout->dir= dir;
+ layout->x= x;
+ layout->y= y;
+ layout->w= w;
+ layout->h= h;
+
+ return layout;
+}
+
+void uiLayoutContext(uiLayout *layout, int opcontext)
+{
+ layout->opcontext= opcontext;
+}
+
+void uiLayoutEnd(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y)
+{
+ ui_layout_end(C, block, layout, x, y);
+ ui_layout_free(layout);
+}
+
+/* Utilities */
+
+static void ui_panel_layout(const bContext *C, ARegion *ar, char *blockname, char *panelname, char *tabname, uiPanelCreateFunc func, int order, int w)
+{
+ uiBlock *block;
+ uiLayout *layout;
+ int xco, yco, x, y;
+
+ // XXX this only hides cruft
+
+ x= 20*order;
+ y= -100*(order+1);
+
+ block= uiBeginBlock(C, ar, blockname, UI_EMBOSS, UI_HELV);
+ if(uiNewPanel(C, ar, block, panelname, tabname, x, y, w, 0)==0) return;
+
+ layout= uiLayoutBegin(UI_LAYOUT_VERTICAL, x, y, w, 0);
+
+ func(C, layout);
+
+ uiLayoutEnd(C, block, layout, &xco, &yco);
+ uiEndBlock(C, block);
+
+ uiNewPanelHeight(block, y - yco + 6);
+}
+
+void uiCompactPanelLayout(const bContext *C, ARegion *ar, char *blockname, char *panelname, char *tabname, uiPanelCreateFunc func, int order)
+{
+ ui_panel_layout(C, ar, blockname, panelname, tabname, func, order, UI_COMPACT_PANEL_WIDTH-22);
+}
+
+void uiPanelLayout(const bContext *C, ARegion *ar, char *blockname, char *panelname, char *tabname, uiPanelCreateFunc func, int order)
+{
+ ui_panel_layout(C, ar, blockname, panelname, tabname, func, order, UI_PANEL_WIDTH-22);
+}
+
+void uiHeaderLayout(const bContext *C, ARegion *ar, uiHeaderCreateFunc func)
+{
+ uiBlock *block;
+ uiLayout *layout;
+ int xco, yco;
+
+ // XXX this only hides cruft
+
+ block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS, UI_HELV);
+ layout= uiLayoutBegin(UI_LAYOUT_HORIZONTAL, 8, 3, 0, 24);
+
+ func(C, layout);
+
+ uiLayoutEnd(C, block, layout, &xco, &yco);
+ uiEndBlock(C, block);
+ uiDrawBlock(C, block);
+
+ /* always as last */
+ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
+}
+
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 6775f6362b8..da70d847176 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -932,8 +932,7 @@ int uiAlignPanelStep(ScrArea *sa, ARegion *ar, float fac)
if(align==BUT_VERTICAL)
ps->pa->ofsy= -ps->pa->sizey-PNL_HEADER-PNL_DIST;
else
- ps->pa->ofsy= 0;
-
+ ps->pa->ofsy= -ps->pa->sizey-PNL_HEADER-PNL_DIST; // XXX was 0;
for(a=0 ; a<tot-1; a++, ps++) {
psnext= ps+1;
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 58563166847..456eae1463d 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -217,7 +217,7 @@ int UI_GetIconRNA(PointerRNA *ptr)
return ICON_DOT;
}
-uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, char *name, int x1, int y1, int x2, int y2)
+uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, char *name, int icon, int x1, int y1, int x2, int y2)
{
uiBut *but=NULL;
const char *propname= RNA_property_identifier(ptr, prop);
@@ -237,10 +237,12 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
else
value= RNA_property_boolean_get(ptr, prop);
- if(name && strcmp(name, "") == 0)
- name= (value)? "Enabled": "Disabled";
-
- but= uiDefButR(block, TOG, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ if(icon && name && strcmp(name, "") == 0)
+ but= uiDefIconButR(block, ICONTOG, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ else if(icon)
+ but= uiDefIconTextButR(block, ICONTOG, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+ else
+ but= uiDefButR(block, TOG, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
break;
}
case PROP_INT:
@@ -267,24 +269,29 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
int icon;
pptr= RNA_property_pointer_get(ptr, prop);
+ descr= (char*)RNA_property_ui_description(ptr, prop);
- if(!pptr.data)
- return NULL;
+ if(!pptr.type)
+ pptr.type= RNA_property_pointer_type(ptr, prop);
icon= UI_GetIconRNA(&pptr);
- nameprop= RNA_struct_name_property(&pptr);
-
- if(nameprop) {
- text= RNA_property_string_get_alloc(&pptr, nameprop, textbuf, sizeof(textbuf));
- descr= (char*)RNA_property_ui_description(&pptr, prop);
- but= uiDefIconTextBut(block, LABEL, 0, icon, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, descr);
- if(text != textbuf)
- MEM_freeN(text);
+
+ if(pptr.data == NULL) {
+ but= uiDefIconTextBut(block, LABEL, 0, icon, "", x1, y1, x2, y2, NULL, 0, 0, 0, 0, "");
}
else {
- text= (char*)RNA_struct_ui_name(&pptr);
- descr= (char*)RNA_property_ui_description(&pptr, prop);
- but= uiDefIconTextBut(block, LABEL, 0, icon, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, descr);
+ nameprop= RNA_struct_name_property(&pptr);
+
+ if(nameprop) {
+ text= RNA_property_string_get_alloc(&pptr, nameprop, textbuf, sizeof(textbuf));
+ but= uiDefIconTextBut(block, LABEL, 0, icon, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, descr);
+ if(text != textbuf)
+ MEM_freeN(text);
+ }
+ else {
+ text= (char*)RNA_struct_ui_name(&pptr);
+ but= uiDefIconTextBut(block, LABEL, 0, icon, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, descr);
+ }
}
break;
}
@@ -338,8 +345,10 @@ int uiDefAutoButsRNA(uiBlock *block, PointerRNA *ptr)
subtype= RNA_property_subtype(ptr, prop);
- name= (char*)RNA_property_ui_name(ptr, prop);
- uiDefBut(block, LABEL, 0, name, x, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1, NULL, 0, 0, 0, 0, "");
+ if(RNA_property_type(ptr, prop) != PROP_BOOLEAN) {
+ name= (char*)RNA_property_ui_name(ptr, prop);
+ uiDefBut(block, LABEL, 0, name, x, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1, NULL, 0, 0, 0, 0, "");
+ }
uiBlockBeginAlign(block);
@@ -355,7 +364,7 @@ int uiDefAutoButsRNA(uiBlock *block, PointerRNA *ptr)
col= a%size;
row= a/size;
- uiDefAutoButR(block, ptr, prop, a, "", x+butwidth*col, y-row*DEF_BUT_HEIGHT, butwidth, DEF_BUT_HEIGHT-1);
+ uiDefAutoButR(block, ptr, prop, a, "", 0, x+butwidth*col, y-row*DEF_BUT_HEIGHT, butwidth, DEF_BUT_HEIGHT-1);
}
y -= DEF_BUT_HEIGHT*(length/size);
@@ -377,7 +386,7 @@ int uiDefAutoButsRNA(uiBlock *block, PointerRNA *ptr)
else
name= coloritem[a];
- uiDefAutoButR(block, ptr, prop, a, name, x+butwidth*a, y, butwidth, DEF_BUT_HEIGHT-1);
+ uiDefAutoButR(block, ptr, prop, a, name, 0, x+butwidth*a, y, butwidth, DEF_BUT_HEIGHT-1);
}
y -= DEF_BUT_HEIGHT;
}
@@ -386,10 +395,12 @@ int uiDefAutoButsRNA(uiBlock *block, PointerRNA *ptr)
sprintf(namebuf, "%d:", a+1);
name= namebuf;
}
+ else if(RNA_property_type(ptr, prop) == PROP_BOOLEAN)
+ name= (char*)RNA_property_ui_name(ptr, prop);
else
name= "";
- uiDefAutoButR(block, ptr, prop, 0, name, x+DEF_BUT_WIDTH, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1);
+ uiDefAutoButR(block, ptr, prop, 0, name, 0, x+DEF_BUT_WIDTH, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1);
y -= DEF_BUT_HEIGHT;
}
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 6e738942e29..d81d9eb79ca 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -249,9 +249,30 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
v2d->tot.ymin= -336.0f*((float)winy)/(float)winx;
v2d->cur= v2d->tot;
+ }
+ break;
+
+ /* panels view, with free/horizontal/vertical align */
+ case V2D_COMMONVIEW_PANELS_UI:
+ {
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ v2d->keepzoom= (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPASPECT|V2D_KEEPZOOM);
+ v2d->minzoom= 0.5f;
+ v2d->maxzoom= 2.0f;
+
+ v2d->align= (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot= V2D_KEEPTOT_BOUNDS;
+ v2d->tot.xmin= 0.0f;
+ v2d->tot.xmax= winx;
+
+ v2d->tot.ymax= 0.0f;
+ v2d->tot.ymin= -winy;
+
+ v2d->cur= v2d->tot;
}
break;
+
/* other view types are completely defined using their own settings already */
default:
/* we don't do anything here, as settings should be fine, but just make sure that rect */