Skip to content

Commit dcf9524

Browse files
authored
Added support for QBoxLayout (#219)
1 parent 3187f8a commit dcf9524

File tree

3 files changed

+165
-126
lines changed

3 files changed

+165
-126
lines changed

src/components/BoxView/RNBoxView.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import {
2+
QWidget,
3+
QBoxLayoutSignals,
4+
QBoxLayout,
5+
NodeWidget,
6+
Direction,
7+
} from "@nodegui/nodegui";
8+
import { ViewProps, setViewProps } from "../View/RNView";
9+
import { RNComponent } from "../config";
10+
11+
export interface BoxViewProps extends ViewProps<QBoxLayoutSignals> {
12+
direction?: Direction;
13+
}
14+
15+
const setBoxViewProps = (
16+
widget: RNBoxView,
17+
newProps: BoxViewProps,
18+
oldProps: BoxViewProps
19+
) => {
20+
const setter: BoxViewProps = {
21+
set direction(direction: Direction) {
22+
widget.layout?.setDirection(direction);
23+
},
24+
};
25+
Object.assign(setter, newProps);
26+
setViewProps(widget, newProps, oldProps);
27+
};
28+
29+
/**
30+
* @ignore
31+
*/
32+
export class RNBoxView extends QWidget implements RNComponent {
33+
native: any;
34+
layout?: QBoxLayout;
35+
initialProps?: BoxViewProps;
36+
children: Array<NodeWidget<any>> = [];
37+
38+
setProps(newProps: BoxViewProps, oldProps: BoxViewProps): void {
39+
if (this.layout) {
40+
setBoxViewProps(this, newProps, oldProps);
41+
} else {
42+
this.initialProps = newProps;
43+
}
44+
}
45+
appendInitialChild(child: NodeWidget<any>): void {
46+
this.appendChild(child);
47+
}
48+
appendChild(child: NodeWidget<any>): void {
49+
const updateChild = () => {
50+
this.layout?.addWidget(child);
51+
this.children.push(child);
52+
};
53+
54+
if (this.layout) {
55+
updateChild();
56+
57+
return;
58+
}
59+
60+
const layout = new QBoxLayout(Direction.LeftToRight);
61+
this.setLayout(layout);
62+
this.layout = layout;
63+
64+
// Newly created layout, so set initial props
65+
if (this.initialProps) {
66+
setBoxViewProps(this, this.initialProps, {});
67+
}
68+
69+
updateChild();
70+
}
71+
insertBefore(child: NodeWidget<any>, beforeChild: NodeWidget<any>): void {
72+
const prevIndex = this.children.indexOf(beforeChild);
73+
74+
if (prevIndex === -1) {
75+
throw new Error(
76+
"Attempted to insert child Node before nonexistent child"
77+
);
78+
}
79+
80+
this.children.splice(prevIndex, 0, child);
81+
this.layout?.insertWidget(prevIndex, child);
82+
}
83+
removeChild(child: NodeWidget<any>): void {
84+
const prevIndex = this.children.indexOf(child);
85+
86+
if (prevIndex !== -1) {
87+
this.children.splice(prevIndex, 1);
88+
}
89+
90+
child.close();
91+
}
92+
static tagName: string = "boxview";
93+
}

src/components/BoxView/index.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { ComponentConfig, registerComponent } from "../config";
2+
import { RNBoxView, BoxViewProps } from "./RNBoxView";
3+
import { AppContainer } from "../../reconciler";
4+
import { Fiber } from "react-reconciler";
5+
6+
class BoxViewConfig extends ComponentConfig {
7+
tagName = RNBoxView.tagName;
8+
shouldSetTextContent(nextProps: BoxViewProps): boolean {
9+
return false;
10+
}
11+
createInstance(
12+
newProps: BoxViewProps,
13+
rootInstance: AppContainer,
14+
context: any,
15+
workInProgress: Fiber
16+
): RNBoxView {
17+
const widget = new RNBoxView();
18+
widget.setProps(newProps, {});
19+
return widget;
20+
}
21+
finalizeInitialChildren(
22+
instance: RNBoxView,
23+
newProps: BoxViewProps,
24+
rootContainerInstance: AppContainer,
25+
context: any
26+
): boolean {
27+
return true;
28+
}
29+
commitMount(
30+
instance: RNBoxView,
31+
newProps: BoxViewProps,
32+
internalInstanceHandle: any
33+
): void {
34+
if (newProps.visible !== false) {
35+
instance.show();
36+
}
37+
}
38+
commitUpdate(
39+
instance: RNBoxView,
40+
updatePayload: any,
41+
oldProps: BoxViewProps,
42+
newProps: BoxViewProps,
43+
finishedWork: Fiber
44+
): void {
45+
instance.setProps(newProps, oldProps);
46+
}
47+
}
48+
49+
export const BoxView = registerComponent<BoxViewProps>(new BoxViewConfig());

src/demo.tsx

Lines changed: 23 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,50 @@
11
import React, { useState } from "react";
2-
import { Renderer, Text, Window, View, Button, useEventHandler } from "./index";
3-
import { GridView } from "./components/GridView";
4-
import { GridRow } from "./components/GridView/GridRow";
5-
import { GridColumn } from "./components/GridView/GridColumn";
6-
import { QPushButtonSignals } from "@nodegui/nodegui";
2+
import { Renderer, Window, Button } from "./index";
3+
import { BoxView } from "./components/BoxView";
4+
import { useEventHandler } from "./hooks";
5+
import { QPushButtonSignals, Direction } from "@nodegui/nodegui";
76

87
const App = () => {
9-
const [additionalRows, setAdditionalRows] = useState<string[]>([]);
10-
const [rowStretch, setRowStretch] = useState(false);
8+
const [additionalButtons, setAdditionalButtons] = useState<string[]>([]);
9+
const [direction, setDirection] = useState<Direction>(Direction.LeftToRight);
1110

12-
const [additionalColumns, setAdditionalColumns] = useState<string[]>([]);
13-
14-
const insertRowHandler = useEventHandler<QPushButtonSignals>(
15-
{
16-
clicked: () =>
17-
setAdditionalRows((rows) => [...rows, `Row ${rows.length}`]),
18-
},
19-
[]
20-
);
21-
22-
const removeRowHandler = useEventHandler<QPushButtonSignals>(
11+
const addHandler = useEventHandler<QPushButtonSignals>(
2312
{
2413
clicked: () =>
25-
setAdditionalRows((rows) => [...rows.slice(0, rows.length - 1)]),
26-
},
27-
[]
28-
);
29-
30-
const insertColumnHandler = useEventHandler<QPushButtonSignals>(
31-
{
32-
clicked: () =>
33-
setAdditionalColumns((columns) => [
34-
...columns,
35-
`Column ${columns.length}`,
14+
setAdditionalButtons((buttons) => [
15+
...buttons,
16+
`Button ${buttons.length}`,
3617
]),
3718
},
3819
[]
3920
);
4021

41-
const removeColumnsHandler = useEventHandler<QPushButtonSignals>(
22+
const removeHandler = useEventHandler<QPushButtonSignals>(
4223
{
4324
clicked: () =>
44-
setAdditionalColumns((columns) => [
45-
...columns.slice(0, columns.length - 1),
46-
]),
25+
setAdditionalButtons((buttons) => buttons.slice(0, buttons.length - 1)),
4726
},
4827
[]
4928
);
5029

51-
const toggleRowStretch = useEventHandler<QPushButtonSignals>(
30+
const toggleDirection = useEventHandler<QPushButtonSignals>(
5231
{
53-
clicked: () => setRowStretch((value) => !value),
32+
clicked: () =>
33+
setDirection((prevDirection) => ((prevDirection + 1) % 4) as Direction),
5434
},
5535
[]
5636
);
5737

5838
return (
5939
<Window>
60-
<GridView
61-
style="flex: 1"
62-
columnProps={{
63-
0: {
64-
minWidth: 200,
65-
},
66-
1: {
67-
minWidth: 300,
68-
},
69-
}}
70-
rowProps={{
71-
0: {
72-
stretch: rowStretch ? 2 : undefined,
73-
minHeight: 400,
74-
},
75-
1: {
76-
stretch: !rowStretch ? 2 : undefined,
77-
},
78-
}}
79-
>
80-
<GridRow>
81-
<GridColumn width={2}>
82-
<View style="background-color: red">
83-
<Text>Hello</Text>
84-
<Button text="Insert row" on={insertRowHandler} />
85-
<Button text="Remove row" on={removeRowHandler} />
86-
<Button text="Toggle row stretch" on={toggleRowStretch} />
87-
<Button text="Insert column" on={insertColumnHandler} />
88-
<Button text="Remove column" on={removeColumnsHandler} />
89-
</View>
90-
</GridColumn>
91-
<GridColumn width={2}>
92-
<View style="background-color: blue">
93-
<Text>Second Column</Text>
94-
</View>
95-
</GridColumn>
96-
<>
97-
{additionalColumns.map((column) => (
98-
<GridColumn key={column}>
99-
<Text>{column}</Text>
100-
</GridColumn>
101-
))}
102-
</>
103-
</GridRow>
104-
<GridRow height={2}>
105-
<GridColumn>
106-
<View style="background-color: green">
107-
<Text>Second row</Text>
108-
</View>
109-
</GridColumn>
110-
<GridColumn>
111-
<View style="background-color: purple">
112-
<Text>Second Column</Text>
113-
</View>
114-
</GridColumn>
115-
<GridColumn>
116-
<View style="background-color: purple">
117-
<Text>Third Column</Text>
118-
</View>
119-
</GridColumn>
120-
<GridColumn>
121-
<View style="background-color: purple">
122-
<Text>Fourth Column</Text>
123-
</View>
124-
</GridColumn>
125-
<>
126-
{additionalColumns.map((column) => (
127-
<GridColumn key={column}>
128-
<Text>Second {column}</Text>
129-
</GridColumn>
130-
))}
131-
</>
132-
</GridRow>
133-
<GridRow>
134-
<GridColumn>
135-
<Text>Third row</Text>
136-
</GridColumn>
137-
</GridRow>
138-
<>
139-
{additionalRows.map((row) => (
140-
<GridRow key={row}>
141-
<GridColumn width={2}>
142-
<Text>{row}</Text>
143-
</GridColumn>
144-
<GridColumn>
145-
<Text>Second {row}</Text>
146-
</GridColumn>
147-
</GridRow>
148-
))}
149-
</>
150-
</GridView>
40+
<BoxView direction={direction}>
41+
<Button text="Add" on={addHandler} />
42+
<Button text="Remove" on={removeHandler} />
43+
<Button text="Toggle direction" on={toggleDirection} />
44+
{additionalButtons.map((button) => (
45+
<Button key={button} text={button} />
46+
))}
47+
</BoxView>
15148
</Window>
15249
);
15350
};

0 commit comments

Comments
 (0)