Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / space_buttons / space_buttons.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_buttons/space_buttons.c
28  *  \ingroup spbuttons
29  */
30
31 #include <string.h>
32 #include <stdio.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_blenlib.h"
37 #include "BLI_utildefines.h"
38
39 #include "BKE_context.h"
40 #include "BKE_screen.h"
41
42 #include "ED_space_api.h"
43 #include "ED_screen.h"
44
45 #include "WM_api.h"
46 #include "WM_types.h"
47 #include "WM_message.h"
48
49 #include "RNA_access.h"
50 #include "RNA_define.h"
51 #include "RNA_enum_types.h"
52
53 #include "UI_resources.h"
54
55 #include "buttons_intern.h"  /* own include */
56
57 /* ******************** default callbacks for buttons space ***************** */
58
59 static SpaceLink *buttons_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
60 {
61         ARegion *ar;
62         SpaceButs *sbuts;
63
64         sbuts = MEM_callocN(sizeof(SpaceButs), "initbuts");
65         sbuts->spacetype = SPACE_BUTS;
66         sbuts->align = BUT_VERTICAL;
67
68         sbuts->mainb = sbuts->mainbuser = BCONTEXT_OBJECT;
69
70         /* header */
71         ar = MEM_callocN(sizeof(ARegion), "header for buts");
72
73         BLI_addtail(&sbuts->regionbase, ar);
74         ar->regiontype = RGN_TYPE_HEADER;
75         ar->alignment = RGN_ALIGN_TOP;
76
77 #if 0
78         /* context region */
79         ar = MEM_callocN(sizeof(ARegion), "context region for buts");
80         BLI_addtail(&sbuts->regionbase, ar);
81         ar->regiontype = RGN_TYPE_CHANNELS;
82         ar->alignment = RGN_ALIGN_TOP;
83 #endif
84
85         /* main region */
86         ar = MEM_callocN(sizeof(ARegion), "main region for buts");
87
88         BLI_addtail(&sbuts->regionbase, ar);
89         ar->regiontype = RGN_TYPE_WINDOW;
90
91         return (SpaceLink *)sbuts;
92 }
93
94 /* not spacelink itself */
95 static void buttons_free(SpaceLink *sl)
96 {
97         SpaceButs *sbuts = (SpaceButs *) sl;
98
99         if (sbuts->path)
100                 MEM_freeN(sbuts->path);
101
102         if (sbuts->texuser) {
103                 ButsContextTexture *ct = sbuts->texuser;
104                 BLI_freelistN(&ct->users);
105                 MEM_freeN(ct);
106         }
107 }
108
109 /* spacetype; init callback */
110 static void buttons_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
111 {
112         SpaceButs *sbuts = sa->spacedata.first;
113
114         /* auto-align based on size */
115         if (sbuts->align == BUT_AUTO || !sbuts->align) {
116                 if (sa->winx > sa->winy)
117                         sbuts->align = BUT_HORIZONTAL;
118                 else
119                         sbuts->align = BUT_VERTICAL;
120         }
121 }
122
123 static SpaceLink *buttons_duplicate(SpaceLink *sl)
124 {
125         SpaceButs *sbutsn = MEM_dupallocN(sl);
126
127         /* clear or remove stuff from old */
128         sbutsn->path = NULL;
129         sbutsn->texuser = NULL;
130
131         return (SpaceLink *)sbutsn;
132 }
133
134 /* add handlers, stuff you only do once or on area/region changes */
135 static void buttons_main_region_init(wmWindowManager *wm, ARegion *ar)
136 {
137         wmKeyMap *keymap;
138
139         ED_region_panels_init(wm, ar);
140
141         keymap = WM_keymap_find(wm->defaultconf, "Property Editor", SPACE_BUTS, 0);
142         WM_event_add_keymap_handler(&ar->handlers, keymap);
143 }
144
145 static void buttons_main_region_draw_properties(const bContext *C, SpaceButs *sbuts, ARegion *ar)
146 {
147         BLI_assert(sbuts->space_subtype == SB_SUBTYPE_DATA);
148         const bool vertical = (sbuts->align == BUT_VERTICAL);
149
150         buttons_context_compute(C, sbuts);
151
152         const char *contexts[2] = {NULL, NULL};
153
154         switch (sbuts->mainb) {
155                 case BCONTEXT_SCENE:
156                         contexts[0] = "scene";
157                         break;
158                 case BCONTEXT_RENDER:
159                         contexts[0] = "render";
160                         break;
161                 case BCONTEXT_VIEW_LAYER:
162                         contexts[0] = "view_layer";
163                         break;
164                 case BCONTEXT_WORLD:
165                         contexts[0] = "world";
166                         break;
167                 case BCONTEXT_WORKSPACE:
168                         contexts[0] = "workspace";
169                         break;
170                 case BCONTEXT_OBJECT:
171                         contexts[0] = "object";
172                         break;
173                 case BCONTEXT_DATA:
174                         contexts[0] = "data";
175                         break;
176                 case BCONTEXT_MATERIAL:
177                         contexts[0] = "material";
178                         break;
179                 case BCONTEXT_TEXTURE:
180                         contexts[0] = "texture";
181                         break;
182                 case BCONTEXT_PARTICLE:
183                         contexts[0] = "particle";
184                         break;
185                 case BCONTEXT_PHYSICS:
186                         contexts[0] = "physics";
187                         break;
188                 case BCONTEXT_BONE:
189                         contexts[0] = "bone";
190                         break;
191                 case BCONTEXT_MODIFIER:
192                         contexts[0] = "modifier";
193                         break;
194                 case BCONTEXT_CONSTRAINT:
195                         contexts[0] = "constraint";
196                         break;
197                 case BCONTEXT_BONE_CONSTRAINT:
198                         contexts[0] = "bone_constraint";
199                         break;
200         }
201
202         if (contexts[0]) {
203                 ED_region_panels(C, ar, contexts, sbuts->mainb, vertical);
204         }
205 }
206
207 static void buttons_main_region_draw_tool(const bContext *C, SpaceButs *sbuts, ARegion *ar)
208 {
209         BLI_assert(sbuts->space_subtype == SB_SUBTYPE_TOOL);
210         const bool vertical = (sbuts->align == BUT_VERTICAL);
211
212         const WorkSpace *workspace = CTX_wm_workspace(C);
213         if (workspace->tools_space_type == SPACE_VIEW3D) {
214                 const int mode = CTX_data_mode_enum(C);
215                 const char *contexts[3] = {NULL};
216                 switch (mode) {
217                         case CTX_MODE_EDIT_MESH:
218                                 ARRAY_SET_ITEMS(contexts, ".mesh_edit");
219                                 break;
220                         case CTX_MODE_EDIT_CURVE:
221                                 ARRAY_SET_ITEMS(contexts, ".curve_edit");
222                                 break;
223                         case CTX_MODE_EDIT_SURFACE:
224                                 ARRAY_SET_ITEMS(contexts, ".curve_edit");
225                                 break;
226                         case CTX_MODE_EDIT_TEXT:
227                                 ARRAY_SET_ITEMS(contexts, ".todo");
228                                 break;
229                         case CTX_MODE_EDIT_ARMATURE:
230                                 ARRAY_SET_ITEMS(contexts, ".armature_edit");
231                                 break;
232                         case CTX_MODE_EDIT_METABALL:
233                                 ARRAY_SET_ITEMS(contexts, ".todo");
234                                 break;
235                         case CTX_MODE_EDIT_LATTICE:
236                                 ARRAY_SET_ITEMS(contexts, ".todo");
237                                 break;
238                         case CTX_MODE_POSE:
239                                 ARRAY_SET_ITEMS(contexts, ".posemode");
240                                 break;
241                         case CTX_MODE_SCULPT:
242                                 ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
243                                 break;
244                         case CTX_MODE_PAINT_WEIGHT:
245                                 ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint");
246                                 break;
247                         case CTX_MODE_PAINT_VERTEX:
248                                 ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint");
249                                 break;
250                         case CTX_MODE_PAINT_TEXTURE:
251                                 ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint");
252                                 break;
253                         case CTX_MODE_PARTICLE:
254                                 ARRAY_SET_ITEMS(contexts, ".particlemode");
255                                 break;
256                         case CTX_MODE_OBJECT:
257                                 ARRAY_SET_ITEMS(contexts, ".todo");
258                                 break;
259                 }
260                 if (contexts[0]) {
261                         ED_region_panels(C, ar, contexts, -1, vertical);
262                 }
263         }
264         else if (workspace->tools_space_type == SPACE_IMAGE) {
265                 /* TODO */
266         }
267 }
268
269 static void buttons_main_region_draw(const bContext *C, ARegion *ar)
270 {
271         /* draw entirely, view changes should be handled here */
272         SpaceButs *sbuts = CTX_wm_space_buts(C);
273
274         if (sbuts->space_subtype == SB_SUBTYPE_DATA) {
275                 buttons_main_region_draw_properties(C, sbuts, ar);
276         }
277         else if (sbuts->space_subtype == SB_SUBTYPE_TOOL) {
278                 buttons_main_region_draw_tool(C, sbuts, ar);
279         }
280
281         sbuts->re_align = 0;
282         sbuts->mainbo = sbuts->mainb;
283 }
284
285 static void buttons_main_region_listener(
286         bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn,
287         const Scene *UNUSED(scene))
288 {
289         /* context changes */
290         switch (wmn->category) {
291                 case NC_SCREEN:
292                         if (ELEM(wmn->data, ND_LAYER)) {
293                                 ED_region_tag_redraw(ar);
294                         }
295                         break;
296         }
297 }
298
299 static void buttons_operatortypes(void)
300 {
301         WM_operatortype_append(BUTTONS_OT_toolbox);
302         WM_operatortype_append(BUTTONS_OT_file_browse);
303         WM_operatortype_append(BUTTONS_OT_directory_browse);
304 }
305
306 static void buttons_keymap(struct wmKeyConfig *keyconf)
307 {
308         wmKeyMap *keymap = WM_keymap_find(keyconf, "Property Editor", SPACE_BUTS, 0);
309
310         WM_keymap_add_item(keymap, "BUTTONS_OT_toolbox", RIGHTMOUSE, KM_PRESS, 0, 0);
311 }
312
313 /* add handlers, stuff you only do once or on area/region changes */
314 static void buttons_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
315 {
316         ED_region_header_init(ar);
317 }
318
319 static void buttons_header_region_draw(const bContext *C, ARegion *ar)
320 {
321         SpaceButs *sbuts = CTX_wm_space_buts(C);
322
323         if (sbuts->space_subtype == SB_SUBTYPE_DATA) {
324                 /* Needed for RNA to get the good values! */
325                 buttons_context_compute(C, sbuts);
326         }
327
328         ED_region_header(C, ar);
329 }
330
331 static void buttons_header_region_message_subscribe(
332         const bContext *UNUSED(C),
333         WorkSpace *UNUSED(workspace), Scene *UNUSED(scene),
334         bScreen *UNUSED(screen), ScrArea *sa, ARegion *ar,
335         struct wmMsgBus *mbus)
336 {
337         SpaceButs *sbuts = sa->spacedata.first;
338         wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
339                 .owner = ar,
340                 .user_data = ar,
341                 .notify = ED_region_do_msg_notify_tag_redraw,
342         };
343
344         /* Don't check for SpaceButs.mainb here, we may toggle between view-layers
345          * where one has no active object, so that available contexts changes. */
346         WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
347
348         if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_WORLD)) {
349                 WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
350         }
351 }
352
353 /* draw a certain button set only if properties area is currently
354  * showing that button set, to reduce unnecessary drawing. */
355 static void buttons_area_redraw(ScrArea *sa, short buttons)
356 {
357         SpaceButs *sbuts = sa->spacedata.first;
358
359         /* if the area's current button set is equal to the one to redraw */
360         if (sbuts->mainb == buttons)
361                 ED_area_tag_redraw(sa);
362 }
363
364 /* reused! */
365 static void buttons_area_listener(
366         bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
367         WorkSpace *UNUSED(workspace))
368 {
369         SpaceButs *sbuts = sa->spacedata.first;
370
371         /* context changes */
372         switch (wmn->category) {
373                 case NC_SCENE:
374                         switch (wmn->data) {
375                                 case ND_RENDER_OPTIONS:
376                                         buttons_area_redraw(sa, BCONTEXT_RENDER);
377                                         buttons_area_redraw(sa, BCONTEXT_VIEW_LAYER);
378                                         break;
379                                 case ND_WORLD:
380                                         buttons_area_redraw(sa, BCONTEXT_WORLD);
381                                         sbuts->preview = 1;
382                                         break;
383                                 case ND_FRAME:
384                                         /* any buttons area can have animated properties so redraw all */
385                                         ED_area_tag_redraw(sa);
386                                         sbuts->preview = 1;
387                                         break;
388                                 case ND_OB_ACTIVE:
389                                         ED_area_tag_redraw(sa);
390                                         sbuts->preview = 1;
391                                         break;
392                                 case ND_KEYINGSET:
393                                         buttons_area_redraw(sa, BCONTEXT_SCENE);
394                                         break;
395                                 case ND_RENDER_RESULT:
396                                         break;
397                                 case ND_MODE:
398                                 case ND_LAYER:
399                                 default:
400                                         ED_area_tag_redraw(sa);
401                                         break;
402                         }
403                         break;
404                 case NC_OBJECT:
405                         switch (wmn->data) {
406                                 case ND_TRANSFORM:
407                                         buttons_area_redraw(sa, BCONTEXT_OBJECT);
408                                         buttons_area_redraw(sa, BCONTEXT_DATA); /* autotexpace flag */
409                                         break;
410                                 case ND_POSE:
411                                         buttons_area_redraw(sa, BCONTEXT_DATA);
412                                         break;
413                                 case ND_BONE_ACTIVE:
414                                 case ND_BONE_SELECT:
415                                         buttons_area_redraw(sa, BCONTEXT_BONE);
416                                         buttons_area_redraw(sa, BCONTEXT_BONE_CONSTRAINT);
417                                         buttons_area_redraw(sa, BCONTEXT_DATA);
418                                         break;
419                                 case ND_MODIFIER:
420                                         if (wmn->action == NA_RENAME)
421                                                 ED_area_tag_redraw(sa);
422                                         else
423                                                 buttons_area_redraw(sa, BCONTEXT_MODIFIER);
424                                         buttons_area_redraw(sa, BCONTEXT_PHYSICS);
425                                         break;
426                                 case ND_CONSTRAINT:
427                                         buttons_area_redraw(sa, BCONTEXT_CONSTRAINT);
428                                         buttons_area_redraw(sa, BCONTEXT_BONE_CONSTRAINT);
429                                         break;
430                                 case ND_PARTICLE:
431                                         if (wmn->action == NA_EDITED)
432                                                 buttons_area_redraw(sa, BCONTEXT_PARTICLE);
433                                         sbuts->preview = 1;
434                                         break;
435                                 case ND_DRAW:
436                                         buttons_area_redraw(sa, BCONTEXT_OBJECT);
437                                         buttons_area_redraw(sa, BCONTEXT_DATA);
438                                         buttons_area_redraw(sa, BCONTEXT_PHYSICS);
439                                         break;
440                                 case ND_SHADING:
441                                 case ND_SHADING_DRAW:
442                                 case ND_SHADING_LINKS:
443                                 case ND_SHADING_PREVIEW:
444                                         /* currently works by redraws... if preview is set, it (re)starts job */
445                                         sbuts->preview = 1;
446                                         break;
447                                 default:
448                                         /* Not all object RNA props have a ND_ notifier (yet) */
449                                         ED_area_tag_redraw(sa);
450                                         break;
451                         }
452                         break;
453                 case NC_GEOM:
454                         switch (wmn->data) {
455                                 case ND_SELECT:
456                                 case ND_DATA:
457                                 case ND_VERTEX_GROUP:
458                                         ED_area_tag_redraw(sa);
459                                         break;
460                         }
461                         break;
462                 case NC_MATERIAL:
463                         ED_area_tag_redraw(sa);
464                         switch (wmn->data) {
465                                 case ND_SHADING:
466                                 case ND_SHADING_DRAW:
467                                 case ND_SHADING_LINKS:
468                                 case ND_SHADING_PREVIEW:
469                                 case ND_NODES:
470                                         /* currently works by redraws... if preview is set, it (re)starts job */
471                                         sbuts->preview = 1;
472                                         break;
473                         }
474                         break;
475                 case NC_WORLD:
476                         buttons_area_redraw(sa, BCONTEXT_WORLD);
477                         sbuts->preview = 1;
478                         break;
479                 case NC_LAMP:
480                         buttons_area_redraw(sa, BCONTEXT_DATA);
481                         sbuts->preview = 1;
482                         break;
483                 case NC_GROUP:
484                         buttons_area_redraw(sa, BCONTEXT_OBJECT);
485                         break;
486                 case NC_BRUSH:
487                         buttons_area_redraw(sa, BCONTEXT_TEXTURE);
488                         sbuts->preview = 1;
489                         break;
490                 case NC_TEXTURE:
491                 case NC_IMAGE:
492                         if (wmn->action != NA_PAINTING) {
493                                 ED_area_tag_redraw(sa);
494                                 sbuts->preview = 1;
495                         }
496                         break;
497                 case NC_SPACE:
498                         if (wmn->data == ND_SPACE_PROPERTIES)
499                                 ED_area_tag_redraw(sa);
500                         break;
501                 case NC_ID:
502                         if (wmn->action == NA_RENAME)
503                                 ED_area_tag_redraw(sa);
504                         break;
505                 case NC_ANIMATION:
506                         switch (wmn->data) {
507                                 case ND_KEYFRAME:
508                                         if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
509                                                 ED_area_tag_redraw(sa);
510                                         break;
511                         }
512                         break;
513                 case NC_NODE:
514                         if (wmn->action == NA_SELECTED) {
515                                 ED_area_tag_redraw(sa);
516                                 /* new active node, update texture preview */
517                                 if (sbuts->mainb == BCONTEXT_TEXTURE)
518                                         sbuts->preview = 1;
519                         }
520                         break;
521                 /* Listener for preview render, when doing an global undo. */
522                 case NC_WM:
523                         if (wmn->data == ND_UNDO) {
524                                 ED_area_tag_redraw(sa);
525                                 sbuts->preview = 1;
526                         }
527                         break;
528 #ifdef WITH_FREESTYLE
529                 case NC_LINESTYLE:
530                         ED_area_tag_redraw(sa);
531                         sbuts->preview = 1;
532                         break;
533 #endif
534         }
535
536         if (wmn->data == ND_KEYS)
537                 ED_area_tag_redraw(sa);
538 }
539
540 static void buttons_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
541 {
542         SpaceButs *sbuts = (SpaceButs *)slink;
543
544         if (sbuts->pinid == old_id) {
545                 sbuts->pinid = new_id;
546                 if (new_id == NULL) {
547                         sbuts->flag &= ~SB_PIN_CONTEXT;
548                 }
549         }
550
551         if (sbuts->path) {
552                 ButsContextPath *path = sbuts->path;
553                 int i;
554
555                 for (i = 0; i < path->len; i++) {
556                         if (path->ptr[i].id.data == old_id) {
557                                 break;
558                         }
559                 }
560
561                 if (i == path->len) {
562                         /* pass */
563                 }
564                 else if (new_id == NULL) {
565                         if (i == 0) {
566                                 MEM_SAFE_FREE(sbuts->path);
567                         }
568                         else {
569                                 memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
570                                 path->len = i;
571                         }
572                 }
573                 else {
574                         RNA_id_pointer_create(new_id, &path->ptr[i]);
575                         /* There is no easy way to check/make path downwards valid, just nullify it.
576                          * Next redraw will rebuild this anyway. */
577                         i++;
578                         memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
579                         path->len = i;
580                 }
581         }
582
583         if (sbuts->texuser) {
584                 ButsContextTexture *ct = sbuts->texuser;
585                 if ((ID *)ct->texture == old_id) {
586                         ct->texture = (Tex *)new_id;
587                 }
588                 BLI_freelistN(&ct->users);
589                 ct->user = NULL;
590         }
591 }
592
593 static int buttons_space_subtype_get(ScrArea *sa)
594 {
595         SpaceButs *sbuts = sa->spacedata.first;
596         return sbuts->space_subtype;
597 }
598
599 static void buttons_space_subtype_set(ScrArea *sa, int value)
600 {
601         SpaceButs *sbuts = sa->spacedata.first;
602         sbuts->space_subtype = value;
603 }
604
605 static void buttons_space_subtype_item_extend(
606         bContext *UNUSED(C), EnumPropertyItem **item, int *totitem)
607 {
608         RNA_enum_items_add(item, totitem, rna_enum_space_button_mode_items);
609 }
610
611 /* only called once, from space/spacetypes.c */
612 void ED_spacetype_buttons(void)
613 {
614         SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype buttons");
615         ARegionType *art;
616
617         st->spaceid = SPACE_BUTS;
618         strncpy(st->name, "Buttons", BKE_ST_MAXNAME);
619
620         st->new = buttons_new;
621         st->free = buttons_free;
622         st->init = buttons_init;
623         st->duplicate = buttons_duplicate;
624         st->operatortypes = buttons_operatortypes;
625         st->keymap = buttons_keymap;
626         st->listener = buttons_area_listener;
627         st->context = buttons_context;
628         st->id_remap = buttons_id_remap;
629         st->space_subtype_item_extend = buttons_space_subtype_item_extend;
630         st->space_subtype_get = buttons_space_subtype_get;
631         st->space_subtype_set = buttons_space_subtype_set;
632
633         /* regions: main window */
634         art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
635         art->regionid = RGN_TYPE_WINDOW;
636         art->init = buttons_main_region_init;
637         art->draw = buttons_main_region_draw;
638         art->listener = buttons_main_region_listener;
639         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
640         BLI_addhead(&st->regiontypes, art);
641
642         buttons_context_register(art);
643
644         /* regions: header */
645         art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
646         art->regionid = RGN_TYPE_HEADER;
647         art->prefsizey = HEADERY;
648         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
649
650         art->init = buttons_header_region_init;
651         art->draw = buttons_header_region_draw;
652         art->message_subscribe = buttons_header_region_message_subscribe;
653         BLI_addhead(&st->regiontypes, art);
654
655         BKE_spacetype_register(st);
656 }
657