Blender V5.0
space_topbar.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2017 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstring>
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_listbase.h"
14#include "BLI_string_utf8.h"
15#include "BLI_utildefines.h"
16
17#include "BLT_translation.hh"
18
19#include "BKE_context.hh"
20#include "BKE_screen.hh"
21#include "BKE_undo_system.hh"
22
23#include "ED_screen.hh"
24#include "ED_space_api.hh"
25
26#include "UI_interface.hh"
28#include "UI_resources.hh"
29#include "UI_view2d.hh"
30
31#include "BLO_read_write.hh"
32
33#include "RNA_access.hh"
34
35#include "WM_api.hh"
36#include "WM_message.hh"
37#include "WM_types.hh"
38
39/* ******************** default callbacks for topbar space ***************** */
40
41static SpaceLink *topbar_create(const ScrArea * /*area*/, const Scene * /*scene*/)
42{
43 ARegion *region;
44 SpaceTopBar *stopbar;
45
46 stopbar = MEM_callocN<SpaceTopBar>("init topbar");
47 stopbar->spacetype = SPACE_TOPBAR;
48
49 /* header */
50 region = BKE_area_region_new();
51 BLI_addtail(&stopbar->regionbase, region);
53 region->alignment = RGN_ALIGN_TOP;
54 region = BKE_area_region_new();
55 BLI_addtail(&stopbar->regionbase, region);
58
59 /* main regions */
60 region = BKE_area_region_new();
61 BLI_addtail(&stopbar->regionbase, region);
63
64 return (SpaceLink *)stopbar;
65}
66
67/* Doesn't free the space-link itself. */
68static void topbar_free(SpaceLink * /*sl*/) {}
69
70/* spacetype; init callback */
71static void topbar_init(wmWindowManager * /*wm*/, ScrArea * /*area*/) {}
72
74{
75 SpaceTopBar *stopbarn = static_cast<SpaceTopBar *>(MEM_dupallocN(sl));
76
77 /* clear or remove stuff from old */
78
79 return (SpaceLink *)stopbarn;
80}
81
82/* add handlers, stuff you only do once or on area/region changes */
84{
85 wmKeyMap *keymap;
86
87 /* force delayed UI_view2d_region_reinit call */
89 region->flag |= RGN_FLAG_DYNAMIC_SIZE;
90 }
91 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_HEADER, region->winx, region->winy);
92
93 keymap = WM_keymap_ensure(
94 wm->runtime->defaultconf, "View2D Buttons List", SPACE_EMPTY, RGN_TYPE_WINDOW);
95 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
96}
97
98static void topbar_operatortypes() {}
99
100static void topbar_keymap(wmKeyConfig * /*keyconf*/) {}
101
102/* add handlers, stuff you only do once or on area/region changes */
104{
106 region->flag |= RGN_FLAG_DYNAMIC_SIZE;
107 }
108 ED_region_header_init(region);
109}
110
112{
113 ARegion *region = params->region;
114 const wmNotifier *wmn = params->notifier;
115
116 /* context changes */
117 switch (wmn->category) {
118 case NC_WM:
119 if (wmn->data == ND_HISTORY) {
120 ED_region_tag_redraw(region);
121 }
122 break;
123 case NC_SCENE:
124 if (wmn->data == ND_MODE) {
125 ED_region_tag_redraw(region);
126 }
127 break;
128 case NC_SPACE:
129 if (wmn->data == ND_SPACE_VIEW3D) {
130 ED_region_tag_redraw(region);
131 }
132 break;
133 case NC_GPENCIL:
134 if (wmn->data == ND_DATA) {
135 ED_region_tag_redraw(region);
136 }
137 break;
138 }
139}
140
142{
143 ARegion *region = params->region;
144 const wmNotifier *wmn = params->notifier;
145
146 /* context changes */
147 switch (wmn->category) {
148 case NC_WM:
149 if (wmn->data == ND_JOB) {
150 ED_region_tag_redraw(region);
151 }
152 break;
153 case NC_WORKSPACE:
154 ED_region_tag_redraw(region);
155 break;
156 case NC_SPACE:
157 if (wmn->data == ND_SPACE_INFO) {
158 ED_region_tag_redraw(region);
159 }
160 break;
161 case NC_SCREEN:
162 if (wmn->data == ND_LAYER) {
163 ED_region_tag_redraw(region);
164 }
165 break;
166 case NC_SCENE:
167 if (wmn->data == ND_SCENEBROWSE) {
168 ED_region_tag_redraw(region);
169 }
170 break;
171 }
172}
173
175{
176 wmMsgBus *mbus = params->message_bus;
177 WorkSpace *workspace = params->workspace;
178 ARegion *region = params->region;
179
180 wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
181 msg_sub_value_region_tag_redraw.owner = region;
182 msg_sub_value_region_tag_redraw.user_data = region;
183 msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
184
186 mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
187}
188
189static void recent_files_menu_draw(const bContext *C, Menu *menu)
190{
191 uiLayout *layout = menu->layout;
193 const bool is_menu_search = CTX_data_int_get(C, "is_menu_search").value_or(false);
194 if (is_menu_search) {
195 uiTemplateRecentFiles(layout, U.recent_files);
196 }
197 else {
198 const int limit = std::min<int>(U.recent_files, 20);
199 if (uiTemplateRecentFiles(layout, limit) != 0) {
200 layout->separator();
201 PointerRNA search_props = layout->op(
202 "WM_OT_search_single_menu", IFACE_("More..."), ICON_VIEWZOOM);
203 RNA_string_set(&search_props, "menu_idname", "TOPBAR_MT_file_open_recent");
204 layout->op("WM_OT_clear_recent_files", IFACE_("Clear Recent Files List..."), ICON_TRASH);
205 }
206 else {
207 layout->label(IFACE_("No Recent Files"), ICON_NONE);
208 }
209 }
210}
211
213{
214 MenuType *mt;
215
216 mt = MEM_callocN<MenuType>("spacetype info menu recent files");
217 STRNCPY_UTF8(mt->idname, "TOPBAR_MT_file_open_recent");
218 STRNCPY_UTF8(mt->label, N_("Open Recent"));
221 WM_menutype_add(mt);
222}
223
224static void undo_history_draw_menu(const bContext *C, Menu *menu)
225{
227 if (wm->runtime->undo_stack == nullptr) {
228 return;
229 }
230
231 int undo_step_count = 0;
232 int undo_step_count_all = 0;
233 LISTBASE_FOREACH_BACKWARD (UndoStep *, us, &wm->runtime->undo_stack->steps) {
234 undo_step_count_all += 1;
235 if (us->skip) {
236 continue;
237 }
238 undo_step_count += 1;
239 }
240
241 uiLayout *split = &menu->layout->split(0.0f, false);
242 uiLayout *column = nullptr;
243
244 const int col_size = 20 + (undo_step_count / 12);
245
246 undo_step_count = 0;
247
248 /* Reverse the order so the most recent state is first in the menu. */
249 int i = undo_step_count_all - 1;
250 for (UndoStep *us = static_cast<UndoStep *>(wm->runtime->undo_stack->steps.last); us;
251 us = us->prev, i--)
252 {
253 if (us->skip) {
254 continue;
255 }
256 if (!(undo_step_count % col_size)) {
257 column = &split->column(false);
258 }
259 const bool is_active = (us == wm->runtime->undo_stack->step_active);
260 uiLayout *row = &column->row(false);
261 row->enabled_set(!is_active);
262 PointerRNA op_ptr = row->op("ED_OT_undo_history",
264 is_active ? ICON_LAYER_ACTIVE : ICON_NONE);
265 RNA_int_set(&op_ptr, "item", i);
266 undo_step_count += 1;
267 }
268}
269
271{
272 MenuType *mt;
273
274 mt = MEM_callocN<MenuType>(__func__);
275 STRNCPY_UTF8(mt->idname, "TOPBAR_MT_undo_history");
276 STRNCPY_UTF8(mt->label, N_("Undo History"));
279 WM_menutype_add(mt);
280}
281
283{
284 BLO_write_struct(writer, SpaceTopBar, sl);
285}
286
288{
289 std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
290 ARegionType *art;
291
292 st->spaceid = SPACE_TOPBAR;
293 STRNCPY_UTF8(st->name, "Top Bar");
294
295 st->create = topbar_create;
296 st->free = topbar_free;
297 st->init = topbar_init;
298 st->duplicate = topbar_duplicate;
299 st->operatortypes = topbar_operatortypes;
300 st->keymap = topbar_keymap;
301 st->blend_write = topbar_space_blend_write;
302
303 /* regions: main window */
304 art = MEM_callocN<ARegionType>("spacetype topbar main region");
310 art->prefsizex = UI_UNIT_X * 5; /* Mainly to avoid glitches */
312
313 BLI_addhead(&st->regiontypes, art);
314
315 /* regions: header */
316 art = MEM_callocN<ARegionType>("spacetype topbar header region");
318 art->prefsizey = HEADERY;
319 art->prefsizex = UI_UNIT_X * 5; /* Mainly to avoid glitches */
326
327 BLI_addhead(&st->regiontypes, art);
328
331
332 BKE_spacetype_register(std::move(st));
333}
std::optional< int64_t > CTX_data_int_get(const bContext *C, const char *member)
wmWindowManager * CTX_wm_manager(const bContext *C)
void BKE_spacetype_register(std::unique_ptr< SpaceType > st)
Definition screen.cc:282
ARegion * BKE_area_region_new()
Definition screen.cc:387
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
#define STRNCPY_UTF8(dst, src)
#define ELEM(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define IFACE_(msgid)
#define BLT_I18NCONTEXT_DEFAULT_BPYRNA
#define HEADERY
#define RGN_ALIGN_ENUM_FROM_MASK(align)
@ RGN_ALIGN_TOP
@ RGN_ALIGN_RIGHT
@ RGN_SPLIT_PREV
@ RGN_TYPE_WINDOW
@ RGN_TYPE_HEADER
@ RGN_FLAG_DYNAMIC_SIZE
@ SPACE_TOPBAR
@ SPACE_EMPTY
void ED_region_header_init(ARegion *region)
Definition area.cc:3950
void ED_region_header_draw(const bContext *C, ARegion *region)
Definition area.cc:3902
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:618
@ ED_KEYMAP_UI
Definition ED_screen.hh:758
@ ED_KEYMAP_HEADER
Definition ED_screen.hh:764
@ ED_KEYMAP_VIEW2D
Definition ED_screen.hh:761
void ED_region_do_msg_notify_tag_redraw(bContext *C, wmMsgSubscribeKey *msg_key, wmMsgSubscribeValue *msg_val)
Definition area.cc:361
void ED_region_header_layout(const bContext *C, ARegion *region)
Definition area.cc:3801
static void split(const char *text, const char *seps, char ***str, int *count)
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
int uiTemplateRecentFiles(uiLayout *layout, int rows)
#define UI_UNIT_X
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
Definition view2d.cc:221
@ V2D_COMMONVIEW_HEADER
Definition UI_view2d.hh:39
#define ND_SPACE_INFO
Definition WM_types.hh:521
#define ND_JOB
Definition WM_types.hh:416
#define NC_WM
Definition WM_types.hh:374
#define ND_DATA
Definition WM_types.hh:509
#define NC_SCREEN
Definition WM_types.hh:377
#define ND_MODE
Definition WM_types.hh:445
#define NC_SCENE
Definition WM_types.hh:378
#define NC_WORKSPACE
Definition WM_types.hh:376
#define NC_GPENCIL
Definition WM_types.hh:399
#define ND_LAYER
Definition WM_types.hh:450
#define ND_HISTORY
Definition WM_types.hh:415
#define ND_SPACE_VIEW3D
Definition WM_types.hh:528
#define ND_SCENEBROWSE
Definition WM_types.hh:432
#define NC_SPACE
Definition WM_types.hh:392
#define U
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
void ED_spacetype_topbar()
static void topbar_init(wmWindowManager *, ScrArea *)
static void recent_files_menu_draw(const bContext *C, Menu *menu)
static void recent_files_menu_register()
static SpaceLink * topbar_create(const ScrArea *, const Scene *)
static void topbar_free(SpaceLink *)
static void topbar_keymap(wmKeyConfig *)
static SpaceLink * topbar_duplicate(SpaceLink *sl)
static void topbar_header_listener(const wmRegionListenerParams *params)
static void topbar_space_blend_write(BlendWriter *writer, SpaceLink *sl)
static void undo_history_menu_register()
static void topbar_header_region_init(wmWindowManager *, ARegion *region)
static void undo_history_draw_menu(const bContext *C, Menu *menu)
static void topbar_main_region_init(wmWindowManager *wm, ARegion *region)
static void topbar_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params)
static void topbar_operatortypes()
static void topbar_main_region_listener(const wmRegionListenerParams *params)
void(* message_subscribe)(const wmRegionMessageSubscribeParams *params)
void(* listener)(const wmRegionListenerParams *params)
void(* draw)(const bContext *C, ARegion *region)
void(* layout)(const bContext *C, ARegion *region)
void(* init)(wmWindowManager *wm, ARegion *region)
ARegionRuntimeHandle * runtime
char label[BKE_ST_MAXNAME]
char idname[BKE_ST_MAXNAME]
void(* draw)(const bContext *C, Menu *menu)
char translation_context[BKE_ST_MAXNAME]
uiLayout * layout
ListBase regionbase
UndoStep * prev
void operator_context_set(blender::wm::OpCallContext opcontext)
void label(blender::StringRef name, int icon)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
void enabled_set(bool enabled)
uiLayout & row(bool align)
uiLayout & split(float percentage, bool align)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
unsigned int data
Definition WM_types.hh:358
unsigned int category
Definition WM_types.hh:358
WindowManagerRuntimeHandle * runtime
i
Definition text_draw.cc:230
#define N_(msgid)
wmEventHandler_Keymap * WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:895
bool WM_menutype_add(MenuType *mt)
#define WM_msg_subscribe_rna_prop(mbus, id_, data_, type_, prop_, value)