Skip to content

Commit da589c5

Browse files
authored
Merge pull request #36 from CodeRibbon/activate-empty-patches
making empty patches focusable
2 parents 3d5052f + 285c0b2 commit da589c5

9 files changed

+308
-55
lines changed

coderibbon-theia/src/browser/coderibbon-theia-commands.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@ import { CodeRibbonTheiaRibbonStrip } from "./cr-ribbon-strip";
1515

1616
import { crdebug } from "./cr-logger";
1717

18-
export const CodeRibbonHelloWorldCommand = {
19-
id: "CodeRibbon.HelloWorld",
20-
label: "Hello, CodeRibbon.",
18+
export const CodeRibbonDebuggingCommands = {
19+
helloWorldCommand: {
20+
id: "CodeRibbon.HelloWorld",
21+
label: "Hello, CodeRibbon.",
22+
},
23+
// testFuzzyFinderCommand: {
24+
// id: "CodeRibbon.dev.test_ff",
25+
// label: "CodeRibbon Test FuzzyFinder",
26+
// },
2127
};
2228

2329
export const CodeRibbonDevGetPanelCommand = {
@@ -138,14 +144,17 @@ export class CodeRibbonTheiaCommandContribution implements CommandContribution {
138144
) {}
139145

140146
registerCommands(registry: CommandRegistry): void {
141-
registry.registerCommand(CodeRibbonHelloWorldCommand, {
147+
// === NOTE: Debugging section
148+
// TODO: only register these in debug mode
149+
150+
registry.registerCommand(CodeRibbonDebuggingCommands.helloWorldCommand, {
142151
execute: () => {
143152
this.messageService.info("CodeRibbon says hello!");
144153
crdebug("Hello console! CommandContribution:", this);
145154
// crdebug("CRAS is:", this.cras);
146155
},
147156
});
148-
// registry.registerCommand(CodeRibbonDevGetPanelCommand, {
157+
// registry.registerCommand(CodeRibbonDebuggingCommands.testFuzzyFinderCommand, {
149158
// execute: () => {
150159
// crdebug();
151160
// }

coderibbon-theia/src/browser/coderibbon-theia-frontend-module.ts

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,84 @@ import {
99
CommandContribution,
1010
MenuModelRegistry,
1111
MessageService,
12+
CorePreferences,
1213
} from "@theia/core/lib/common";
14+
import { PreferenceContribution } from "@theia/core/lib/common/preferences";
15+
import { ApplicationShell } from "@theia/core/lib/browser/shell/application-shell";
1316
import {
14-
// FrontendApplicationContribution,
15-
// bindViewContribution, WidgetFactory,
17+
bindViewContribution,
18+
DockPanel,
19+
FrontendApplicationContribution,
1620
KeybindingContribution,
21+
WidgetFactory,
22+
WidgetManager,
1723
} from "@theia/core/lib/browser";
18-
import { PreferenceContribution } from "@theia/core/lib/common/preferences";
19-
import { ApplicationShell } from "@theia/core/lib/browser/shell/application-shell";
2024

2125
// import { CodeRibbonTheiaRibbonViewContribution } from './coderibbon-theia-ribbon';
2226
import { CodeRibbonTheiaCommandContribution } from "./coderibbon-theia-commands";
2327
import { CodeRibbonTheiaMenuContribution } from "./coderibbon-theia-menus";
2428
import { CodeRibbonTheiaPreferenceSchema } from "./coderibbon-theia-preferences";
2529
import { CodeRibbonTheiaManager } from "./coderibbon-theia-manager";
26-
import { CodeRibbonTheiaRibbonPanel } from "./cr-ribbon";
2730
import { CodeRibbonApplicationShell } from "./cr-application-shell";
31+
import { CodeRibbonTheiaRibbonPanel } from "./cr-ribbon";
32+
import { CodeRibbonTheiaPatch } from "./cr-patch";
2833
import { CodeRibbonTheiaKeybindingContribution } from "./coderibbon-theia-keybinds";
34+
import {
35+
CodeRibbonFuzzyFileOpenerWidget,
36+
CodeRibbonFuzzyFileOpenerContribution,
37+
} from "./cr-fuzzy-file-opener";
2938

3039
import "../../src/browser/style/ribbon.less";
3140
// temp CSS
3241
import "../../src/browser/style/debug.less";
42+
import { crdebug } from "./cr-logger";
43+
import { TheiaDockPanel } from "@theia/core/lib/browser/shell/theia-dock-panel";
3344

3445
export default new ContainerModule((bind, unbind, isBound, rebind) => {
3546
bind(CodeRibbonApplicationShell).toSelf().inSingletonScope();
3647
// get rid of original ApplicationShell:
3748
// @ts-ignore
3849
rebind(ApplicationShell).to(CodeRibbonApplicationShell).inSingletonScope();
3950

51+
// this is how we sneak the inversify container into the non-injectable CR classes
52+
// (instead of doing the cheap/unstable window.theia.container workaround)
53+
bind(CodeRibbonTheiaRibbonPanel.Factory).toFactory(
54+
({ container }) =>
55+
(options: Partial<CodeRibbonTheiaRibbonPanel.IOptions>) => {
56+
return new CodeRibbonTheiaRibbonPanel({
57+
alignment: "start",
58+
direction: "left-to-right",
59+
spacing: 0,
60+
mode: "multiple-document",
61+
container,
62+
...options,
63+
});
64+
},
65+
);
66+
4067
bind(CommandContribution).to(CodeRibbonTheiaCommandContribution);
4168
bind(MenuContribution).to(CodeRibbonTheiaMenuContribution);
4269
bind(KeybindingContribution).to(CodeRibbonTheiaKeybindingContribution);
4370

71+
// crdebug("now binding the CRFFO widget");
72+
// CRFFO widget
73+
bind(CodeRibbonFuzzyFileOpenerWidget).toSelf();
74+
bind(WidgetFactory)
75+
.toDynamicValue((ctx) => ({
76+
id: CodeRibbonFuzzyFileOpenerWidget.ID,
77+
createWidget: () =>
78+
ctx.container.get<CodeRibbonFuzzyFileOpenerWidget>(
79+
CodeRibbonFuzzyFileOpenerWidget,
80+
),
81+
}))
82+
.inSingletonScope();
83+
84+
// opener
85+
bindViewContribution(bind, CodeRibbonFuzzyFileOpenerContribution);
86+
bind(FrontendApplicationContribution).toService(
87+
CodeRibbonFuzzyFileOpenerContribution,
88+
);
89+
4490
// TODO fix prefs
4591
// bind(PreferenceContribution).toConstantValue({
4692
// schema: CodeRibbonTheiaPreferenceSchema});

coderibbon-theia/src/browser/coderibbon-theia-menus.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import {
1212
} from "@theia/core/lib/common";
1313

1414
import {
15-
CodeRibbonHelloWorldCommand,
15+
CodeRibbonDebuggingCommands,
1616
CodeRibbonNavigationCommands,
1717
CodeRibbonManipulationCommands,
1818
CodeRibbonArrangementCommands,
1919
} from "./coderibbon-theia-commands";
2020

21+
import { TestOpenFFOCommand } from "./cr-fuzzy-file-opener";
22+
2123
export const CodeRibbonTopMenuPath = [...MAIN_MENU_BAR, "7_coderibbon"];
2224
export const CodeRibbonNavigationMenu = [
2325
...CodeRibbonTopMenuPath,
@@ -38,9 +40,12 @@ export class CodeRibbonTheiaMenuContribution implements MenuContribution {
3840
registerMenus(menus: MenuModelRegistry): void {
3941
menus.registerSubmenu(CodeRibbonTopMenuPath, "CodeRibbon");
4042

43+
// General
44+
4145
menus.registerMenuAction(CodeRibbonTopMenuPath, {
42-
commandId: CodeRibbonHelloWorldCommand.id,
43-
label: "Say Hello",
46+
// commandId: CodeRibbonDebuggingCommands.testFuzzyFinderCommand.id,
47+
commandId: TestOpenFFOCommand.id,
48+
label: "Test FuzzyFinder",
4449
});
4550

4651
// Navigation

coderibbon-theia/src/browser/cr-application-shell.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { FrontendApplicationStateService } from "@theia/core/lib/browser/fronten
2424
import { CorePreferences } from "@theia/core/lib/common/core-preferences";
2525
import {
2626
TheiaDockPanel,
27-
BOTTOM_AREA_ID,
27+
// BOTTOM_AREA_ID,
2828
MAIN_AREA_ID,
2929
// MAXIMIZED_CLASS,
3030
} from "@theia/core/lib/browser/shell/theia-dock-panel";
@@ -56,10 +56,25 @@ export class CodeRibbonApplicationShell extends ApplicationShell {
5656
// @ts-expect-error TS2416: Property in type is not assignable to the same property in base type
5757
override mainPanel: CodeRibbonTheiaRibbonPanel;
5858

59+
// ApplicationShell only supplies the DockPanel renderer
60+
// other constructor requirements are in the factory itself
61+
@inject(CodeRibbonTheiaRibbonPanel.Factory)
62+
protected readonly ribbonPanelFactory: ({
63+
renderer,
64+
}: {
65+
renderer: DockPanelRenderer;
66+
}) => CodeRibbonTheiaRibbonPanel;
67+
5968
/**
6069
* Create the dock panel in the main shell area.
6170
*
6271
* Override the default from using TheiaDockPanel to CodeRibbonTheiaRibbonPanel
72+
* this is a modification of:
73+
* https://github.com/eclipse-theia/theia/blob/008c8340465f7e42298839881d814863bef0b039/packages/core/src/browser/shell/application-shell.ts#L579-L591
74+
* expect to have to update this if the upstream behavior changes
75+
*
76+
* Q: Why not just override the dockPanelFactory?
77+
* A: because it's also used to create the bottom panel & it's not indicated at construction which it will be
6378
*/
6479
// @ts-expect-error TS2416: Property in type is not assignable to the same property in base type
6580
override createMainPanel(): CodeRibbonTheiaRibbonPanel {
@@ -91,11 +106,15 @@ export class CodeRibbonApplicationShell extends ApplicationShell {
91106
// }, this.corePreferences);
92107

93108
// what I want, based on BoxPanel
94-
const ribbonPanel = new CodeRibbonTheiaRibbonPanel({
95-
alignment: "start",
96-
direction: "left-to-right",
97-
spacing: 0,
98-
mode: "multiple-document",
109+
// const ribbonPanel = new CodeRibbonTheiaRibbonPanel({
110+
// alignment: "start",
111+
// direction: "left-to-right",
112+
// spacing: 0,
113+
// mode: "multiple-document",
114+
// renderer,
115+
// // widgetManager: this.widgetManager,
116+
// });
117+
const ribbonPanel = this.ribbonPanelFactory({
99118
renderer,
100119
});
101120

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import * as React from "react";
2+
import {
3+
injectable,
4+
postConstruct,
5+
inject,
6+
} from "@theia/core/shared/inversify";
7+
import { AlertMessage } from "@theia/core/lib/browser/widgets/alert-message";
8+
import { ReactWidget } from "@theia/core/lib/browser/widgets/react-widget";
9+
import { MessageService } from "@theia/core";
10+
import { Message, QuickInputService, InputBox } from "@theia/core/lib/browser";
11+
import { AbstractViewContribution } from "@theia/core/lib/browser";
12+
import { Command, CommandRegistry } from "@theia/core/lib/common/command";
13+
import { crdebug } from "./cr-logger";
14+
15+
import { QuickFileSelectService } from "@theia/file-search/lib/browser/quick-file-select-service";
16+
import { MonacoQuickInputService } from "@theia/monaco/lib/browser/monaco-quick-input-service";
17+
18+
/**
19+
* since this is registered in theia's WidgetManager / WidgetFactory it is part of the inversify container (hence injectable)
20+
*/
21+
@injectable()
22+
export class CodeRibbonFuzzyFileOpenerWidget extends ReactWidget {
23+
static readonly ID = "coderibbon:fuzzy-file-opener";
24+
static readonly LABEL = "CodeRibbon Fuzzy File Finder";
25+
26+
// protected current_search?: string = undefined;
27+
// TODO this should be the monaco input / quick open equivalent
28+
// protected inputElement?: HTMLInputElement;
29+
protected inputElementRef: React.RefObject<HTMLInputElement>;
30+
31+
@inject(QuickInputService)
32+
protected readonly quickInputService: QuickInputService;
33+
34+
@inject(QuickFileSelectService)
35+
protected readonly quickFileSelectService: QuickFileSelectService;
36+
37+
@inject(MonacoQuickInputService)
38+
protected readonly monacoQuickInputService: MonacoQuickInputService;
39+
40+
@inject(MessageService)
41+
protected readonly messageService!: MessageService;
42+
43+
@postConstruct()
44+
protected init(): void {
45+
crdebug("CRFFO postConstruct");
46+
this.id = CodeRibbonFuzzyFileOpenerWidget.ID;
47+
this.title.label = CodeRibbonFuzzyFileOpenerWidget.LABEL;
48+
this.title.caption = CodeRibbonFuzzyFileOpenerWidget.LABEL;
49+
this.title.closable = true;
50+
this.title.iconClass = "fa fa-window-maximize"; // example widget icon.
51+
52+
this.inputElementRef = React.createRef();
53+
// TODO how?
54+
// this.inputBox = this.quickInputService.createInputBox();
55+
this.update();
56+
}
57+
58+
activate(): void {
59+
this.inputElementRef.current?.focus();
60+
}
61+
62+
render(): React.ReactElement {
63+
const header = `Does not work yet. Eventually this should be the same UI as Ctrl-P.`;
64+
const show_fuzzy_search: boolean = true;
65+
return (
66+
<div id="widget-container">
67+
<AlertMessage type="INFO" header={header} />
68+
{/* <button
69+
className="theia-button secondary"
70+
title="Display Message"
71+
onClick={(_a) => this.displayMessage()}
72+
>
73+
Display Message
74+
</button> */}
75+
<input
76+
ref={this.inputElementRef}
77+
name="search"
78+
placeholder="search project files..."
79+
autoComplete="off"
80+
/>
81+
</div>
82+
);
83+
}
84+
85+
protected displayMessage(): void {
86+
this.messageService.info(
87+
"Congratulations: My Widget Successfully Created!",
88+
);
89+
}
90+
}
91+
92+
export const TestOpenFFOCommand: Command = { id: "coderibbon:test-ffo" };
93+
94+
@injectable()
95+
export class CodeRibbonFuzzyFileOpenerContribution extends AbstractViewContribution<CodeRibbonFuzzyFileOpenerWidget> {
96+
constructor() {
97+
super({
98+
widgetId: CodeRibbonFuzzyFileOpenerWidget.ID,
99+
widgetName: CodeRibbonFuzzyFileOpenerWidget.LABEL,
100+
defaultWidgetOptions: { area: "main" },
101+
toggleCommandId: TestOpenFFOCommand.id,
102+
});
103+
}
104+
105+
registerCommands(commands: CommandRegistry): void {
106+
commands.registerCommand(TestOpenFFOCommand, {
107+
execute: () => {
108+
crdebug("command: TestOpenFFOCommand executes");
109+
super.openView({ activate: false, reveal: true });
110+
},
111+
});
112+
}
113+
114+
// registerMenus(menus:)
115+
}

coderibbon-theia/src/browser/cr-interfaces.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,6 @@ export namespace RibbonPanel {
6666
* areas, and those areas can be individually resized by the user.
6767
*/
6868
| "multiple-document";
69-
export interface IOptions {
70-
direction?: BoxLayout.Direction; // only horizontal
71-
alignment?: BoxLayout.Alignment; // only ...
72-
spacing?: number;
73-
layout?: CodeRibbonTheiaRibbonLayout;
74-
mode: RibbonPanel.Mode;
75-
renderer?: DockLayout.IRenderer;
76-
}
7769
export interface ILayoutConfig {
7870
// TODO actual definition of serializable layout config
7971
// NOTE probably a sequence of RibbonStrip.ILayoutConfig ???

0 commit comments

Comments
 (0)