From 1be40439b0cef692622cf7e061850ec5e1a2db36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Kr=C3=B6hnke?= Date: Thu, 14 Oct 2021 15:57:00 +0900 Subject: [PATCH] Add `List` and `ListItem` using `QListWidget` and `QListWidgetItem` ``` Hello World ``` --- src/components/List/RNList.ts | 58 ++++++++++++++++++++++++++ src/components/List/index.ts | 43 +++++++++++++++++++ src/components/ListItem/RNListItem.ts | 59 +++++++++++++++++++++++++++ src/components/ListItem/index.ts | 40 ++++++++++++++++++ src/index.ts | 2 + 5 files changed, 202 insertions(+) create mode 100644 src/components/List/RNList.ts create mode 100644 src/components/List/index.ts create mode 100644 src/components/ListItem/RNListItem.ts create mode 100644 src/components/ListItem/index.ts diff --git a/src/components/List/RNList.ts b/src/components/List/RNList.ts new file mode 100644 index 0000000..86c4bd6 --- /dev/null +++ b/src/components/List/RNList.ts @@ -0,0 +1,58 @@ +import { FlexLayout, QListWidget, QListWidgetSignals } from "@nodegui/nodegui"; +import { ViewProps, setViewProps } from "../View/RNView"; +import { RNComponent } from "../config"; +import { RNListItem } from "../ListItem/RNListItem"; + + +export interface ListProps extends ViewProps { +} + +type CustomListProps = ListProps; + + +/** + * @ignore + */ +export const setListProps = (widget: RNList, newProps: CustomListProps, oldProps: CustomListProps) => { + + const setter: CustomListProps = { + }; + Object.assign(setter, newProps); + setViewProps(widget, newProps, oldProps); +}; + +/** + * @ignore + */ +export class RNList extends QListWidget implements RNComponent { + setProps(newProps: CustomListProps, oldProps: CustomListProps): void { + setListProps(this, newProps, oldProps); + } + removeChild(child: RNListItem): void { + const row = this.row(child); + this.takeItem(row); + } + appendInitialChild(child: RNListItem): void { + this.appendChild(child); + } + appendChild(child: RNListItem): void { + if (!this.layout) { + this.setLayout(new FlexLayout()); + } + + if (!(child instanceof RNListItem)) { + throw new Error("Children of list should be of type ListItem"); + } + + this.addItem(child); + if (child.actualListItemWidget) { + child.setSizeHint(child.actualListItemWidget.size()); + this.setItemWidget(child, child.actualListItemWidget); + } + } + insertBefore(child: RNListItem, beforeChild: RNListItem): void { + const row = this.row(beforeChild); + this.insertItem(row, child); + } + static tagName = "list"; +} diff --git a/src/components/List/index.ts b/src/components/List/index.ts new file mode 100644 index 0000000..6f1c3e5 --- /dev/null +++ b/src/components/List/index.ts @@ -0,0 +1,43 @@ +import { registerComponent, ComponentConfig } from "../config"; +import { Fiber } from "react-reconciler"; +import { RNList, ListProps } from "./RNList"; +import { AppContainer } from "../../reconciler"; + +class ListConfig extends ComponentConfig { + tagName = RNList.tagName; + shouldSetTextContent(nextProps: ListProps): boolean { + return false; + } + createInstance(newProps: ListProps, rootInstance: AppContainer, context: any, workInProgress: Fiber): RNList { + const widget = new RNList(); + widget.setProps(newProps, {}); + return widget; + } + commitMount(instance: RNList, newProps: ListProps, internalInstanceHandle: any): void { + if (newProps.visible !== false) { + instance.show(); + } + return; + } + commitUpdate(instance: RNList, updatePayload: any, oldProps: ListProps, newProps: ListProps, finishedWork: Fiber): void { + instance.setProps(newProps, oldProps); + } +} +/** + * React implementation of nodegui's [QListWidget](https://docs.nodegui.org/docs/api/generated/classes/qlistwidget/) + * @example + * ```javascriptreact + * return ( + * + + + + Hello World + + + + * ) + * ``` + */ + +export const List = registerComponent(new ListConfig()); diff --git a/src/components/ListItem/RNListItem.ts b/src/components/ListItem/RNListItem.ts new file mode 100644 index 0000000..148385f --- /dev/null +++ b/src/components/ListItem/RNListItem.ts @@ -0,0 +1,59 @@ +import { NodeWidget, QListWidgetItem, QIcon } from "@nodegui/nodegui"; +import { RNComponent } from "../config"; + +export interface ListItemProps { + title?: string; + icon?: QIcon; +} + +/** + * @ignore + */ +export const setListItemProps = ( + widget: RNListItem, + newProps: ListItemProps, + oldProps: ListItemProps +) => { + const setter: ListItemProps = { + set title(text: string) { + widget.setText(text); + }, + set icon(qicon: QIcon) { + widget.setIcon(qicon); + } + }; + Object.assign(setter, newProps); +}; + +/** + * @ignore + */ +export class RNListItem extends QListWidgetItem implements RNComponent { + native: any; + actualListItemWidget?: NodeWidget; + + setProps(newProps: ListItemProps, oldProps: ListItemProps): void { + setListItemProps(this, newProps, oldProps); + } + appendInitialChild(child: NodeWidget): void { + if (this.actualListItemWidget) { + throw new Error("ListItem can have only one child"); + } + this.actualListItemWidget = child; + } + appendChild(child: NodeWidget): void { + this.appendInitialChild(child); + } + insertBefore(child: NodeWidget, beforeChild: NodeWidget): void { + this.appendInitialChild(child); + } + removeChild(child: NodeWidget): void { + if (child) { + child.close(); + } + if (this.actualListItemWidget) { + delete this.actualListItemWidget; + } + } + static tagName: string = "listitem"; +} diff --git a/src/components/ListItem/index.ts b/src/components/ListItem/index.ts new file mode 100644 index 0000000..7bee20b --- /dev/null +++ b/src/components/ListItem/index.ts @@ -0,0 +1,40 @@ +import { Fiber } from "react-reconciler"; +import { registerComponent, ComponentConfig } from "../config"; +import { RNListItem, ListItemProps } from "./RNListItem"; +import { AppContainer } from "../../reconciler"; + +class ListItemConfig extends ComponentConfig { + tagName = RNListItem.tagName; + shouldSetTextContent(nextProps: ListItemProps): boolean { + return false; + } + createInstance( + newProps: ListItemProps, + rootInstance: AppContainer, + context: any, + workInProgress: Fiber + ): RNListItem { + const item = new RNListItem(); + item.setProps(newProps, {}); + return item; + } + finalizeInitialChildren( + instance: RNListItem, + newProps: ListItemProps, + rootContainerInstance: AppContainer, + context: any + ): boolean { + return false; + } + commitUpdate( + instance: RNListItem, + updatePayload: any, + oldProps: ListItemProps, + newProps: ListItemProps, + finishedWork: Fiber + ): void { + instance.setProps(newProps, oldProps); + } +} + +export const ListItem = registerComponent(new ListItemConfig()); diff --git a/src/index.ts b/src/index.ts index a61d0ac..cc196b6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,6 +32,8 @@ export { InputDialog } from "./components/InputDialog"; export { ProgressDialog } from "./components/ProgressDialog"; export { Table } from "./components/Table"; export { TableItem } from "./components/TableItem"; +export { List } from "./components/List"; +export { ListItem } from "./components/ListItem"; export { ErrorPrompt } from "./components/ErrorPrompt" export { useEventHandler } from "./hooks"; export { Renderer } from "./renderer";