@lvce-editor/title-bar-worker 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/titleBarWorkerMain.js +277 -215
- package/package.json +1 -1
|
@@ -1354,10 +1354,15 @@ const getMenuVirtualDom = menuItems => {
|
|
|
1354
1354
|
};
|
|
1355
1355
|
|
|
1356
1356
|
const HandleClick = 'handleClick';
|
|
1357
|
+
const HandleClickMinimize = 'handleClickMinimize';
|
|
1358
|
+
const HandleClickToggleClose = 'handleClickToggleClose';
|
|
1359
|
+
const HandleClickToggleMaximize = 'handleClickToggleMaximize';
|
|
1357
1360
|
const HandleFocusIn = 'handleFocusIn';
|
|
1358
1361
|
const HandleFocusOut = 'handleFocusOut';
|
|
1359
1362
|
const HandlePointerOut = 'handlePointerOut';
|
|
1360
1363
|
const HandlePointerOver = 'handlePointerOver';
|
|
1364
|
+
const HandleMenuClick = 'handleMenuClick';
|
|
1365
|
+
const HandleMenuMouseOver = 'handleMenuMouseOver';
|
|
1361
1366
|
|
|
1362
1367
|
const getItemVirtualDom = item => {
|
|
1363
1368
|
// @ts-ignore
|
|
@@ -1600,7 +1605,8 @@ const doRender = async uid => {
|
|
|
1600
1605
|
return commands;
|
|
1601
1606
|
};
|
|
1602
1607
|
|
|
1603
|
-
const commandsIds = ['closeMenu', 'focus', 'focusFirst', 'focusIndex', 'focusLast', 'focusNext', 'focusPrevious', 'handleKeyArrowDown', 'handleKeyArrowLeft', 'handleKeyArrowRight', 'handleKeyArrowUp', 'handleKeyEnd', 'handleKeyEnter', 'handleKeyEscape', 'handleKeyHome', 'handleKeySpace', 'handleMenuClick', 'handleMenuMouseOver', '
|
|
1608
|
+
const commandsIds = ['closeMenu', 'focus', 'focusFirst', 'focusIndex', 'focusLast', 'focusNext', 'focusPrevious', 'handleClick', 'handleFocus', 'handleKeyArrowDown', 'handleKeyArrowLeft', 'handleKeyArrowRight', 'handleKeyArrowUp', 'handleKeyEnd', 'handleKeyEnter', 'handleKeyEscape', 'handleKeyHome', 'handleKeySpace', 'handleMenuClick', 'handleMenuMouseOver', 'handleMouseOut', 'handleMouseOver', 'handlePointerOver', 'handlePointerOut', 'toggleIndex', 'toggleMenu'];
|
|
1609
|
+
|
|
1604
1610
|
const getCommandIds = () => {
|
|
1605
1611
|
return commandsIds;
|
|
1606
1612
|
};
|
|
@@ -2288,6 +2294,248 @@ const handleContextMenu = state => {
|
|
|
2288
2294
|
return state;
|
|
2289
2295
|
};
|
|
2290
2296
|
|
|
2297
|
+
const getTitleBarIndexFromPosition = (titleBarEntries, x, y) => {
|
|
2298
|
+
let currentX = 0;
|
|
2299
|
+
for (let i = 0; i < titleBarEntries.length; i++) {
|
|
2300
|
+
const entry = titleBarEntries[i];
|
|
2301
|
+
const entryWidth = entry.width;
|
|
2302
|
+
if (x >= currentX && x < currentX + entryWidth) {
|
|
2303
|
+
return i;
|
|
2304
|
+
}
|
|
2305
|
+
currentX += entryWidth;
|
|
2306
|
+
}
|
|
2307
|
+
return -1;
|
|
2308
|
+
};
|
|
2309
|
+
|
|
2310
|
+
const getTotalWidth = entries => {
|
|
2311
|
+
let total = 0;
|
|
2312
|
+
for (const entry of entries) {
|
|
2313
|
+
total += entry.width;
|
|
2314
|
+
}
|
|
2315
|
+
return total;
|
|
2316
|
+
};
|
|
2317
|
+
|
|
2318
|
+
// TODO lazyload menuEntries and use Command.execute (maybe)
|
|
2319
|
+
const CONTEXT_MENU_ITEM_HEIGHT = 26;
|
|
2320
|
+
const CONTEXT_MENU_SEPARATOR_HEIGHT = 11;
|
|
2321
|
+
const CONTEXT_MENU_PADDING = 8;
|
|
2322
|
+
const getMenuHeight = items => {
|
|
2323
|
+
let height = CONTEXT_MENU_PADDING;
|
|
2324
|
+
for (const item of items) {
|
|
2325
|
+
switch (item.flags) {
|
|
2326
|
+
case Separator:
|
|
2327
|
+
height += CONTEXT_MENU_SEPARATOR_HEIGHT;
|
|
2328
|
+
break;
|
|
2329
|
+
default:
|
|
2330
|
+
height += CONTEXT_MENU_ITEM_HEIGHT;
|
|
2331
|
+
break;
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
return height;
|
|
2335
|
+
};
|
|
2336
|
+
|
|
2337
|
+
// TODO lazyload menuEntries and use Command.execute (maybe)
|
|
2338
|
+
const MENU_WIDTH = 150;
|
|
2339
|
+
const CONTEXT_MENU_WIDTH = 250;
|
|
2340
|
+
const getMenuWidth = () => {
|
|
2341
|
+
return CONTEXT_MENU_WIDTH;
|
|
2342
|
+
};
|
|
2343
|
+
|
|
2344
|
+
// TODO difference between focusing with mouse or keyboard
|
|
2345
|
+
// with mouse -> open submenu
|
|
2346
|
+
// with keyboard -> don't open submenu, only focus
|
|
2347
|
+
|
|
2348
|
+
const getIndexToFocusNextStartingAt = (items, startIndex) => {
|
|
2349
|
+
for (let i = startIndex; i < startIndex + items.length; i++) {
|
|
2350
|
+
const index = i % items.length;
|
|
2351
|
+
const item = items[index];
|
|
2352
|
+
if (canBeFocused(item)) {
|
|
2353
|
+
return index;
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
return -1;
|
|
2357
|
+
};
|
|
2358
|
+
const getIndexToFocusFirst = items => {
|
|
2359
|
+
return getIndexToFocusNextStartingAt(items, 0);
|
|
2360
|
+
};
|
|
2361
|
+
const getIndexToFocusLast = items => {
|
|
2362
|
+
return getIndexToFocusPreviousStartingAt(items, items.length - 1);
|
|
2363
|
+
};
|
|
2364
|
+
|
|
2365
|
+
// TODO this code seems a bit too complicated, maybe it can be simplified
|
|
2366
|
+
const getIndexToFocusPreviousStartingAt = (items, startIndex) => {
|
|
2367
|
+
for (let i = startIndex; i > startIndex - items.length; i--) {
|
|
2368
|
+
const index = (i + items.length) % items.length;
|
|
2369
|
+
const item = items[index];
|
|
2370
|
+
if (canBeFocused(item)) {
|
|
2371
|
+
return index;
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
return -1;
|
|
2375
|
+
};
|
|
2376
|
+
const getIndexToFocusPrevious = menu => {
|
|
2377
|
+
const startIndex = menu.focusedIndex === -1 ? menu.items.length - 1 : menu.focusedIndex - 1;
|
|
2378
|
+
return getIndexToFocusPreviousStartingAt(menu.items, startIndex);
|
|
2379
|
+
};
|
|
2380
|
+
const canBeFocused = item => {
|
|
2381
|
+
switch (item.flags) {
|
|
2382
|
+
case Separator:
|
|
2383
|
+
case Disabled:
|
|
2384
|
+
return false;
|
|
2385
|
+
default:
|
|
2386
|
+
return true;
|
|
2387
|
+
}
|
|
2388
|
+
};
|
|
2389
|
+
const getIndexToFocusNext = menu => {
|
|
2390
|
+
const startIndex = menu.focusedIndex + 1;
|
|
2391
|
+
return getIndexToFocusNextStartingAt(menu.items, startIndex);
|
|
2392
|
+
};
|
|
2393
|
+
|
|
2394
|
+
// TODO handle printable letter and focus item that starts with that letter
|
|
2395
|
+
|
|
2396
|
+
// TODO pageup / pagedown keys
|
|
2397
|
+
|
|
2398
|
+
// TODO more tests
|
|
2399
|
+
|
|
2400
|
+
const menus = [MenuEntriesEdit, MenuEntriesFile, MenuEntriesGo, MenuEntriesHelp, MenuEntriesRun, MenuEntriesSelection, MenuEntriesTerminal, MenuEntriesTitleBar, MenuEntriesView, MenuEntriesOpenRecent];
|
|
2401
|
+
const getMenus = () => {
|
|
2402
|
+
return menus;
|
|
2403
|
+
};
|
|
2404
|
+
const getModule = id => {
|
|
2405
|
+
for (const module of menus) {
|
|
2406
|
+
if (module.id === id) {
|
|
2407
|
+
return module;
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
return undefined;
|
|
2411
|
+
};
|
|
2412
|
+
const getMenuEntries = async (id, ...args) => {
|
|
2413
|
+
try {
|
|
2414
|
+
const module = getModule(id);
|
|
2415
|
+
// @ts-ignore
|
|
2416
|
+
const inject = module.inject || [];
|
|
2417
|
+
// @ts-ignore
|
|
2418
|
+
return module.getMenuEntries(...args);
|
|
2419
|
+
} catch (error) {
|
|
2420
|
+
throw new VError(error, `Failed to load menu entries for id ${id}`);
|
|
2421
|
+
}
|
|
2422
|
+
};
|
|
2423
|
+
|
|
2424
|
+
const openMenuAtIndex = async (state, index, shouldBeFocused) => {
|
|
2425
|
+
const {
|
|
2426
|
+
titleBarEntries,
|
|
2427
|
+
titleBarHeight,
|
|
2428
|
+
x
|
|
2429
|
+
} = state;
|
|
2430
|
+
// TODO race conditions
|
|
2431
|
+
// TODO send renderer process
|
|
2432
|
+
// 1. open menu, items to show
|
|
2433
|
+
// 2. focus menu
|
|
2434
|
+
const titleBarEntry = titleBarEntries[index];
|
|
2435
|
+
const {
|
|
2436
|
+
id
|
|
2437
|
+
} = titleBarEntry;
|
|
2438
|
+
const items = await getMenuEntries(id);
|
|
2439
|
+
const relevantEntries = titleBarEntries.slice(0, index);
|
|
2440
|
+
const totalWidths = getTotalWidth(relevantEntries);
|
|
2441
|
+
const offset = totalWidths;
|
|
2442
|
+
// TODO race condition: another menu might already be open at this point
|
|
2443
|
+
|
|
2444
|
+
const menuX = x + offset;
|
|
2445
|
+
const menuY = titleBarHeight;
|
|
2446
|
+
const width = getMenuWidth();
|
|
2447
|
+
const height = getMenuHeight(items);
|
|
2448
|
+
const menuFocusedIndex = shouldBeFocused ? getIndexToFocusNextStartingAt(items, 0) : -1;
|
|
2449
|
+
const menu = {
|
|
2450
|
+
id,
|
|
2451
|
+
items,
|
|
2452
|
+
focusedIndex: menuFocusedIndex,
|
|
2453
|
+
level: 0,
|
|
2454
|
+
x: menuX,
|
|
2455
|
+
y: menuY,
|
|
2456
|
+
width,
|
|
2457
|
+
height
|
|
2458
|
+
};
|
|
2459
|
+
const menus = [menu];
|
|
2460
|
+
return {
|
|
2461
|
+
...state,
|
|
2462
|
+
isMenuOpen: true,
|
|
2463
|
+
focusedIndex: index,
|
|
2464
|
+
menus
|
|
2465
|
+
};
|
|
2466
|
+
};
|
|
2467
|
+
|
|
2468
|
+
const focusIndex = async (state, index) => {
|
|
2469
|
+
object(state);
|
|
2470
|
+
number(index);
|
|
2471
|
+
const {
|
|
2472
|
+
isMenuOpen,
|
|
2473
|
+
focusedIndex
|
|
2474
|
+
} = state;
|
|
2475
|
+
if (index === focusedIndex) {
|
|
2476
|
+
return state;
|
|
2477
|
+
}
|
|
2478
|
+
if (isMenuOpen) {
|
|
2479
|
+
return openMenuAtIndex(state, index, /* focus */false);
|
|
2480
|
+
}
|
|
2481
|
+
return {
|
|
2482
|
+
...state,
|
|
2483
|
+
focusedIndex: index
|
|
2484
|
+
};
|
|
2485
|
+
};
|
|
2486
|
+
|
|
2487
|
+
const handleMouseOutMenuClosed = state => {
|
|
2488
|
+
return focusIndex(state, -1);
|
|
2489
|
+
};
|
|
2490
|
+
|
|
2491
|
+
const handleMouseOutMenuOpen = state => {
|
|
2492
|
+
return state;
|
|
2493
|
+
};
|
|
2494
|
+
|
|
2495
|
+
const ifElse = (menuOpenFunction, menuClosedFunction) => {
|
|
2496
|
+
const ifElseFunction = (state, ...args) => {
|
|
2497
|
+
const {
|
|
2498
|
+
isMenuOpen
|
|
2499
|
+
} = state;
|
|
2500
|
+
if (isMenuOpen) {
|
|
2501
|
+
return menuOpenFunction(state, ...args);
|
|
2502
|
+
}
|
|
2503
|
+
return menuClosedFunction(state, ...args);
|
|
2504
|
+
};
|
|
2505
|
+
return ifElseFunction;
|
|
2506
|
+
};
|
|
2507
|
+
|
|
2508
|
+
const handleMouseOut = ifElse(handleMouseOutMenuOpen, handleMouseOutMenuClosed);
|
|
2509
|
+
|
|
2510
|
+
const handlePointerOut = (state, clientX, clientY) => {
|
|
2511
|
+
const index = getTitleBarIndexFromPosition(state.titleBarEntries, clientX - state.x);
|
|
2512
|
+
if (index === -1) {
|
|
2513
|
+
return state;
|
|
2514
|
+
}
|
|
2515
|
+
return handleMouseOut(state, index);
|
|
2516
|
+
};
|
|
2517
|
+
|
|
2518
|
+
const handleMouseOverMenuClosed = (state, index) => {
|
|
2519
|
+
return focusIndex(state, index);
|
|
2520
|
+
};
|
|
2521
|
+
|
|
2522
|
+
const handleMouseOverMenuOpen = async (state, index) => {
|
|
2523
|
+
if (index === -1) {
|
|
2524
|
+
return state;
|
|
2525
|
+
}
|
|
2526
|
+
return focusIndex(state, index);
|
|
2527
|
+
};
|
|
2528
|
+
|
|
2529
|
+
const handleMouseOver = ifElse(handleMouseOverMenuOpen, handleMouseOverMenuClosed);
|
|
2530
|
+
|
|
2531
|
+
const handlePointerOver = (state, clientX, clientY) => {
|
|
2532
|
+
const index = getTitleBarIndexFromPosition(state.titleBarEntries, clientX - state.x);
|
|
2533
|
+
if (index === -1) {
|
|
2534
|
+
return state;
|
|
2535
|
+
}
|
|
2536
|
+
return handleMouseOver(state, index);
|
|
2537
|
+
};
|
|
2538
|
+
|
|
2291
2539
|
const getFontString = (fontWeight, fontSize, fontFamily) => {
|
|
2292
2540
|
return `${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
2293
2541
|
};
|
|
@@ -2380,40 +2628,37 @@ const loadContent = async (state, titleBarEntries) => {
|
|
|
2380
2628
|
};
|
|
2381
2629
|
};
|
|
2382
2630
|
|
|
2383
|
-
const menus = [MenuEntriesEdit, MenuEntriesFile, MenuEntriesGo, MenuEntriesHelp, MenuEntriesRun, MenuEntriesSelection, MenuEntriesTerminal, MenuEntriesTitleBar, MenuEntriesView, MenuEntriesOpenRecent];
|
|
2384
|
-
const getMenus = () => {
|
|
2385
|
-
return menus;
|
|
2386
|
-
};
|
|
2387
|
-
const getModule = id => {
|
|
2388
|
-
for (const module of menus) {
|
|
2389
|
-
if (module.id === id) {
|
|
2390
|
-
return module;
|
|
2391
|
-
}
|
|
2392
|
-
}
|
|
2393
|
-
return undefined;
|
|
2394
|
-
};
|
|
2395
|
-
const getMenuEntries = async (id, ...args) => {
|
|
2396
|
-
try {
|
|
2397
|
-
const module = getModule(id);
|
|
2398
|
-
// @ts-ignore
|
|
2399
|
-
const inject = module.inject || [];
|
|
2400
|
-
// @ts-ignore
|
|
2401
|
-
return module.getMenuEntries(...args);
|
|
2402
|
-
} catch (error) {
|
|
2403
|
-
throw new VError(error, `Failed to load menu entries for id ${id}`);
|
|
2404
|
-
}
|
|
2405
|
-
};
|
|
2406
|
-
|
|
2407
2631
|
const renderEventListeners = () => {
|
|
2408
2632
|
return [{
|
|
2409
|
-
name:
|
|
2633
|
+
name: HandleClickMinimize,
|
|
2410
2634
|
params: ['handleClickMinimize']
|
|
2411
2635
|
}, {
|
|
2412
|
-
name:
|
|
2636
|
+
name: HandleClickToggleClose,
|
|
2413
2637
|
params: ['handleClickClose']
|
|
2414
2638
|
}, {
|
|
2415
|
-
name:
|
|
2639
|
+
name: HandleClickToggleMaximize,
|
|
2416
2640
|
params: ['handleClickToggleMaximize']
|
|
2641
|
+
}, {
|
|
2642
|
+
name: HandleFocusIn,
|
|
2643
|
+
params: ['handlefocus']
|
|
2644
|
+
}, {
|
|
2645
|
+
name: HandleMenuClick,
|
|
2646
|
+
params: ['handleMenuClick', 'event.clientX', 'event.clientY']
|
|
2647
|
+
}, {
|
|
2648
|
+
name: HandleMenuMouseOver,
|
|
2649
|
+
params: ['handleMenuMouseOver', 'event.clientX', 'event.clientY']
|
|
2650
|
+
}, {
|
|
2651
|
+
name: HandleClick,
|
|
2652
|
+
params: ['handleClick', 'event.button', 'event.clientX', 'event.clientY']
|
|
2653
|
+
}, {
|
|
2654
|
+
name: HandlePointerOut,
|
|
2655
|
+
params: ['handlePointerOut', 'event.clientX', 'event.clientY']
|
|
2656
|
+
}, {
|
|
2657
|
+
name: HandlePointerOver,
|
|
2658
|
+
params: ['handlePointerOver', 'event.clientX', 'event.clientY']
|
|
2659
|
+
}, {
|
|
2660
|
+
name: HandleFocusOut,
|
|
2661
|
+
params: ['handleFocusOut', 'event.clientX', 'event.clientY'] // TODO maybe check relatedTarget
|
|
2417
2662
|
}];
|
|
2418
2663
|
};
|
|
2419
2664
|
|
|
@@ -2476,155 +2721,6 @@ const previous = (items, index) => {
|
|
|
2476
2721
|
return index === 0 ? items.length - 1 : index - 1;
|
|
2477
2722
|
};
|
|
2478
2723
|
|
|
2479
|
-
const getTotalWidth = entries => {
|
|
2480
|
-
let total = 0;
|
|
2481
|
-
for (const entry of entries) {
|
|
2482
|
-
total += entry.width;
|
|
2483
|
-
}
|
|
2484
|
-
return total;
|
|
2485
|
-
};
|
|
2486
|
-
|
|
2487
|
-
// TODO lazyload menuEntries and use Command.execute (maybe)
|
|
2488
|
-
const CONTEXT_MENU_ITEM_HEIGHT = 26;
|
|
2489
|
-
const CONTEXT_MENU_SEPARATOR_HEIGHT = 11;
|
|
2490
|
-
const CONTEXT_MENU_PADDING = 8;
|
|
2491
|
-
const getMenuHeight = items => {
|
|
2492
|
-
let height = CONTEXT_MENU_PADDING;
|
|
2493
|
-
for (const item of items) {
|
|
2494
|
-
switch (item.flags) {
|
|
2495
|
-
case Separator:
|
|
2496
|
-
height += CONTEXT_MENU_SEPARATOR_HEIGHT;
|
|
2497
|
-
break;
|
|
2498
|
-
default:
|
|
2499
|
-
height += CONTEXT_MENU_ITEM_HEIGHT;
|
|
2500
|
-
break;
|
|
2501
|
-
}
|
|
2502
|
-
}
|
|
2503
|
-
return height;
|
|
2504
|
-
};
|
|
2505
|
-
|
|
2506
|
-
// TODO lazyload menuEntries and use Command.execute (maybe)
|
|
2507
|
-
const MENU_WIDTH = 150;
|
|
2508
|
-
const CONTEXT_MENU_WIDTH = 250;
|
|
2509
|
-
const getMenuWidth = () => {
|
|
2510
|
-
return CONTEXT_MENU_WIDTH;
|
|
2511
|
-
};
|
|
2512
|
-
|
|
2513
|
-
// TODO difference between focusing with mouse or keyboard
|
|
2514
|
-
// with mouse -> open submenu
|
|
2515
|
-
// with keyboard -> don't open submenu, only focus
|
|
2516
|
-
|
|
2517
|
-
const getIndexToFocusNextStartingAt = (items, startIndex) => {
|
|
2518
|
-
for (let i = startIndex; i < startIndex + items.length; i++) {
|
|
2519
|
-
const index = i % items.length;
|
|
2520
|
-
const item = items[index];
|
|
2521
|
-
if (canBeFocused(item)) {
|
|
2522
|
-
return index;
|
|
2523
|
-
}
|
|
2524
|
-
}
|
|
2525
|
-
return -1;
|
|
2526
|
-
};
|
|
2527
|
-
const getIndexToFocusFirst = items => {
|
|
2528
|
-
return getIndexToFocusNextStartingAt(items, 0);
|
|
2529
|
-
};
|
|
2530
|
-
const getIndexToFocusLast = items => {
|
|
2531
|
-
return getIndexToFocusPreviousStartingAt(items, items.length - 1);
|
|
2532
|
-
};
|
|
2533
|
-
|
|
2534
|
-
// TODO this code seems a bit too complicated, maybe it can be simplified
|
|
2535
|
-
const getIndexToFocusPreviousStartingAt = (items, startIndex) => {
|
|
2536
|
-
for (let i = startIndex; i > startIndex - items.length; i--) {
|
|
2537
|
-
const index = (i + items.length) % items.length;
|
|
2538
|
-
const item = items[index];
|
|
2539
|
-
if (canBeFocused(item)) {
|
|
2540
|
-
return index;
|
|
2541
|
-
}
|
|
2542
|
-
}
|
|
2543
|
-
return -1;
|
|
2544
|
-
};
|
|
2545
|
-
const getIndexToFocusPrevious = menu => {
|
|
2546
|
-
const startIndex = menu.focusedIndex === -1 ? menu.items.length - 1 : menu.focusedIndex - 1;
|
|
2547
|
-
return getIndexToFocusPreviousStartingAt(menu.items, startIndex);
|
|
2548
|
-
};
|
|
2549
|
-
const canBeFocused = item => {
|
|
2550
|
-
switch (item.flags) {
|
|
2551
|
-
case Separator:
|
|
2552
|
-
case Disabled:
|
|
2553
|
-
return false;
|
|
2554
|
-
default:
|
|
2555
|
-
return true;
|
|
2556
|
-
}
|
|
2557
|
-
};
|
|
2558
|
-
const getIndexToFocusNext = menu => {
|
|
2559
|
-
const startIndex = menu.focusedIndex + 1;
|
|
2560
|
-
return getIndexToFocusNextStartingAt(menu.items, startIndex);
|
|
2561
|
-
};
|
|
2562
|
-
|
|
2563
|
-
// TODO handle printable letter and focus item that starts with that letter
|
|
2564
|
-
|
|
2565
|
-
// TODO pageup / pagedown keys
|
|
2566
|
-
|
|
2567
|
-
// TODO more tests
|
|
2568
|
-
|
|
2569
|
-
const openMenuAtIndex = async (state, index, shouldBeFocused) => {
|
|
2570
|
-
const {
|
|
2571
|
-
titleBarEntries,
|
|
2572
|
-
titleBarHeight,
|
|
2573
|
-
x
|
|
2574
|
-
} = state;
|
|
2575
|
-
// TODO race conditions
|
|
2576
|
-
// TODO send renderer process
|
|
2577
|
-
// 1. open menu, items to show
|
|
2578
|
-
// 2. focus menu
|
|
2579
|
-
const titleBarEntry = titleBarEntries[index];
|
|
2580
|
-
const {
|
|
2581
|
-
id
|
|
2582
|
-
} = titleBarEntry;
|
|
2583
|
-
const items = await getMenuEntries(id);
|
|
2584
|
-
const relevantEntries = titleBarEntries.slice(0, index);
|
|
2585
|
-
const totalWidths = getTotalWidth(relevantEntries);
|
|
2586
|
-
const offset = totalWidths;
|
|
2587
|
-
// TODO race condition: another menu might already be open at this point
|
|
2588
|
-
|
|
2589
|
-
const menuX = x + offset;
|
|
2590
|
-
const menuY = titleBarHeight;
|
|
2591
|
-
const width = getMenuWidth();
|
|
2592
|
-
const height = getMenuHeight(items);
|
|
2593
|
-
const menuFocusedIndex = shouldBeFocused ? getIndexToFocusNextStartingAt(items, 0) : -1;
|
|
2594
|
-
const menu = {
|
|
2595
|
-
id,
|
|
2596
|
-
items,
|
|
2597
|
-
focusedIndex: menuFocusedIndex,
|
|
2598
|
-
level: 0,
|
|
2599
|
-
x: menuX,
|
|
2600
|
-
y: menuY,
|
|
2601
|
-
width,
|
|
2602
|
-
height
|
|
2603
|
-
};
|
|
2604
|
-
const menus = [menu];
|
|
2605
|
-
return {
|
|
2606
|
-
...state,
|
|
2607
|
-
isMenuOpen: true,
|
|
2608
|
-
focusedIndex: index,
|
|
2609
|
-
menus
|
|
2610
|
-
};
|
|
2611
|
-
};
|
|
2612
|
-
|
|
2613
|
-
const focusIndex = async (state, index) => {
|
|
2614
|
-
object(state);
|
|
2615
|
-
number(index);
|
|
2616
|
-
const {
|
|
2617
|
-
isMenuOpen
|
|
2618
|
-
} = state;
|
|
2619
|
-
if (isMenuOpen) {
|
|
2620
|
-
return openMenuAtIndex(state, index, /* focus */false);
|
|
2621
|
-
}
|
|
2622
|
-
return {
|
|
2623
|
-
...state,
|
|
2624
|
-
focusedIndex: index
|
|
2625
|
-
};
|
|
2626
|
-
};
|
|
2627
|
-
|
|
2628
2724
|
const focusFirst = state => {
|
|
2629
2725
|
const indexToFocus = first();
|
|
2630
2726
|
return focusIndex(state, indexToFocus);
|
|
@@ -2662,7 +2758,7 @@ const focusPrevious = state => {
|
|
|
2662
2758
|
|
|
2663
2759
|
const LeftClick = 0;
|
|
2664
2760
|
|
|
2665
|
-
const toggleIndex = (state, index) => {
|
|
2761
|
+
const toggleIndex = async (state, index) => {
|
|
2666
2762
|
const {
|
|
2667
2763
|
isMenuOpen,
|
|
2668
2764
|
focusedIndex
|
|
@@ -2673,7 +2769,7 @@ const toggleIndex = (state, index) => {
|
|
|
2673
2769
|
return openMenuAtIndex(state, index, /* focus */false);
|
|
2674
2770
|
};
|
|
2675
2771
|
|
|
2676
|
-
const handleClick = (state, button, index) => {
|
|
2772
|
+
const handleClick = async (state, button, index) => {
|
|
2677
2773
|
if (button !== LeftClick) {
|
|
2678
2774
|
return state;
|
|
2679
2775
|
}
|
|
@@ -2724,19 +2820,6 @@ const handleKeyArrowDownMenuOpen = state => {
|
|
|
2724
2820
|
};
|
|
2725
2821
|
};
|
|
2726
2822
|
|
|
2727
|
-
const ifElse = (menuOpenFunction, menuClosedFunction) => {
|
|
2728
|
-
const ifElseFunction = (state, ...args) => {
|
|
2729
|
-
const {
|
|
2730
|
-
isMenuOpen
|
|
2731
|
-
} = state;
|
|
2732
|
-
if (isMenuOpen) {
|
|
2733
|
-
return menuOpenFunction(state, ...args);
|
|
2734
|
-
}
|
|
2735
|
-
return menuClosedFunction(state, ...args);
|
|
2736
|
-
};
|
|
2737
|
-
return ifElseFunction;
|
|
2738
|
-
};
|
|
2739
|
-
|
|
2740
2823
|
const handleKeyArrowDown = ifElse(handleKeyArrowDownMenuOpen, handleKeyArrowDownMenuClosed);
|
|
2741
2824
|
|
|
2742
2825
|
const handleKeyArrowLeftMenuClosed = state => {
|
|
@@ -3061,29 +3144,6 @@ const handleMenuMouseOver = async (state, level, index) => {
|
|
|
3061
3144
|
};
|
|
3062
3145
|
};
|
|
3063
3146
|
|
|
3064
|
-
const handleMouseOutMenuClosed = state => {
|
|
3065
|
-
return focusIndex(state, -1);
|
|
3066
|
-
};
|
|
3067
|
-
|
|
3068
|
-
const handleMouseOutMenuOpen = state => {
|
|
3069
|
-
return state;
|
|
3070
|
-
};
|
|
3071
|
-
|
|
3072
|
-
const handleMouseOut = ifElse(handleMouseOutMenuOpen, handleMouseOutMenuClosed);
|
|
3073
|
-
|
|
3074
|
-
const handleMouseOverMenuClosed = (state, index) => {
|
|
3075
|
-
return focusIndex(state, index);
|
|
3076
|
-
};
|
|
3077
|
-
|
|
3078
|
-
const handleMouseOverMenuOpen = async (state, index) => {
|
|
3079
|
-
if (index === -1) {
|
|
3080
|
-
return state;
|
|
3081
|
-
}
|
|
3082
|
-
return focusIndex(state, index);
|
|
3083
|
-
};
|
|
3084
|
-
|
|
3085
|
-
const handleMouseOver = ifElse(handleMouseOverMenuOpen, handleMouseOverMenuClosed);
|
|
3086
|
-
|
|
3087
3147
|
const toggleMenu = state => {
|
|
3088
3148
|
const {
|
|
3089
3149
|
isMenuOpen
|
|
@@ -3132,8 +3192,10 @@ const commandMap = {
|
|
|
3132
3192
|
'TitleBarMenuBar.handleKeyArrowLeft': wrapCommand(handleKeyArrowLeft),
|
|
3133
3193
|
'TitleBarMenuBar.handleKeyArrowRight': wrapCommand(handleKeyArrowRight),
|
|
3134
3194
|
'TitleBarMenuBar.handleKeyArrowUp': wrapCommand(handleKeyArrowUp),
|
|
3195
|
+
'TitleBarMenuBar.handlePointerOver': wrapCommand(handlePointerOver),
|
|
3135
3196
|
'TitleBarMenuBar.handleKeyEnd': wrapCommand(handleKeyEnd),
|
|
3136
3197
|
'TitleBarMenuBar.handleKeyEnter': wrapCommand(handleKeyEnter),
|
|
3198
|
+
'TitleBarMenuBar.handlePointerOut': wrapCommand(handlePointerOut),
|
|
3137
3199
|
'TitleBarMenuBar.handleKeyEscape': wrapCommand(handleKeyEscape),
|
|
3138
3200
|
'TitleBarMenuBar.handleKeyHome': wrapCommand(handleKeyHome),
|
|
3139
3201
|
'TitleBarMenuBar.handleKeySpace': wrapCommand(handleKeySpace),
|