Adds inline styling support and other native methods
This commit is contained in:
parent
c3de181e32
commit
4f9e27d36a
22
demo.ts
22
demo.ts
@ -3,16 +3,20 @@ import {
|
||||
QWidget,
|
||||
QLabel,
|
||||
FlexLayout,
|
||||
StyleSheet,
|
||||
QPushButton
|
||||
} from "./src/lib/index";
|
||||
|
||||
const win = new QMainWindow();
|
||||
//-------------------------------
|
||||
const centralWidget = new QWidget();
|
||||
centralWidget.setObjectName("myroot");
|
||||
const rootLayout = new FlexLayout();
|
||||
centralWidget.setLayout(rootLayout);
|
||||
const view = new QWidget();
|
||||
const viewLayout = new FlexLayout();
|
||||
view.setInlineStyle(
|
||||
`margin-top:20px; background: url(${"/Users/atulr/Downloads/photo.jpeg"});`
|
||||
);
|
||||
view.setLayout(viewLayout);
|
||||
//--------------------------------------
|
||||
const label = new QLabel();
|
||||
label.setObjectName("mylabel");
|
||||
@ -22,22 +26,20 @@ const btn = new QPushButton();
|
||||
btn.setText("Yo button");
|
||||
btn.setObjectName("btn");
|
||||
//--------------------------------------
|
||||
rootLayout.addWidget(label);
|
||||
rootLayout.addWidget(btn);
|
||||
viewLayout.addWidget(label);
|
||||
viewLayout.addWidget(btn);
|
||||
rootLayout.addWidget(view);
|
||||
win.setCentralWidget(centralWidget);
|
||||
const winStyleSheet = StyleSheet.create(`
|
||||
#myroot {
|
||||
background-color: #009688;
|
||||
}
|
||||
const winStyleSheet = `
|
||||
#mylabel {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-top: 30px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
#btn {
|
||||
margin-top: 30px;
|
||||
}
|
||||
`);
|
||||
`;
|
||||
win.setStyleSheet(winStyleSheet);
|
||||
win.show();
|
||||
win.resize(400, 500);
|
||||
|
||||
@ -82,6 +82,10 @@ Sets the property that holds the widget's style sheet. It calls the native metho
|
||||
|
||||
- `styleSheet` string - String which holds the widget's style sheet. Make sure you create this string using `StyleSheet.create()`
|
||||
|
||||
#### `widget.styleSheet()`
|
||||
|
||||
Gets the property that holds the widget's style sheet. It calls the native method [QWidget: styleSheet](https://doc.qt.io/qt-5/qwidget.html#styleSheet-prop).
|
||||
|
||||
#### `widget.hide()`
|
||||
|
||||
Hides the widget and its children. It calls the native method [QWidget: hide](https://doc.qt.io/qt-5/qwidget.html#hide).
|
||||
@ -92,6 +96,10 @@ Sets the object name of the widget in Qt. It calls the native method [QObject: s
|
||||
|
||||
- `objectName` string - String which holds the widget's object name.
|
||||
|
||||
#### `widget.objectName()`
|
||||
|
||||
Gets the property that holds the widget's object name. It calls the native method [QObject: setObjectName](https://doc.qt.io/qt-5/qobject.html#objectName-prop).
|
||||
|
||||
#### `widget.setMouseTracking(isMouseTracked)`
|
||||
|
||||
Sets the property that tells whether mouseTracking is enabled for the widget. It calls the native method [QWidget: mouseTracking](https://doc.qt.io/qt-5/qwidget.html#mouseTracking-prop).
|
||||
@ -140,3 +148,16 @@ returns the current widget size. It calls the native method [QWidget: size](http
|
||||
#### `widget.updateGeometry()`
|
||||
|
||||
Notifies the layout system that this widget has changed and may need to change geometry.
|
||||
|
||||
#### `widget.setAttribute(attributeName, switchOn)`
|
||||
|
||||
Sets the attribute attribute on this widget if on is true; otherwise clears the attribute. It calls the native method [QWidget: setAttribute](https://doc.qt.io/qt-5/qwidget.html#setAttribute).
|
||||
|
||||
- `attributeName` WidgetAttribute - Enum from WidgetAttribute.
|
||||
- `switchOn` - set it to true if you want to enable an attribute.
|
||||
|
||||
#### `widget.testAttribute(attributeName)`
|
||||
|
||||
Returns true if attribute attribute is set on this widget; otherwise returns false. It calls the native method [QWidget: testAttribute](https://doc.qt.io/qt-5/qwidget.html#testAttribute).
|
||||
|
||||
- `attributeName` WidgetAttribute - Enum from WidgetAttribute.
|
||||
|
||||
@ -8,7 +8,6 @@ import {
|
||||
import { QLabel } from "../../src/lib/QtWidgets/QLabel";
|
||||
import { BaseWidgetEvents } from "../../src/lib/core/EventWidget";
|
||||
import { QKeyEvent } from "../../src/lib/QtGui/QEvent/QKeyEvent";
|
||||
import { StyleSheet } from "../../src/lib";
|
||||
|
||||
const globals = global as any;
|
||||
|
||||
@ -47,8 +46,7 @@ win.addEventListener(BaseWidgetEvents.KeyRelease, nativeEvent => {
|
||||
});
|
||||
rootView.setObjectName("rootView"); //This is like ids in web world
|
||||
win.setCentralWidget(rootView);
|
||||
const rootStyleSheet = StyleSheet.create(
|
||||
`
|
||||
const rootStyleSheet = `
|
||||
* {
|
||||
font-size: 20px;
|
||||
color: white;
|
||||
@ -111,10 +109,9 @@ QPushButton:pressed {
|
||||
#row2 QPushButton:pressed, #row2 QPushButton:pressed, #row3 QPushButton:pressed, #row4 QPushButton:pressed {
|
||||
background: grey;
|
||||
}
|
||||
`
|
||||
);
|
||||
`;
|
||||
|
||||
const operatorStyleSheet = StyleSheet.create(`
|
||||
const operatorStyleSheet = `
|
||||
QPushButton {
|
||||
background: #FD8D0E;
|
||||
}
|
||||
@ -122,7 +119,7 @@ QPushButton {
|
||||
QPushButton:pressed {
|
||||
background: grey;
|
||||
}
|
||||
`);
|
||||
`;
|
||||
|
||||
rootView.setStyleSheet(rootStyleSheet);
|
||||
const rootViewFlexLayout = new FlexLayout();
|
||||
|
||||
5
package-lock.json
generated
5
package-lock.json
generated
@ -407,6 +407,11 @@
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"cuid": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/cuid/-/cuid-2.1.6.tgz",
|
||||
"integrity": "sha512-ZFp7PS6cSYMJNch9fc3tyHdE4T8TDo3Y5qAxb0KSA9mpiYDo7z9ql1CznFuuzxea9STVIDy0tJWm2lYiX2ZU1Q=="
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
"dependencies": {
|
||||
"@nodegui/test": "^0.0.10",
|
||||
"bindings": "^1.5.0",
|
||||
"cuid": "^2.1.6",
|
||||
"node-addon-api": "^1.6.3",
|
||||
"node-gyp": "^4.0.0",
|
||||
"postcss-nodegui-autoprefixer": "0.0.7"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const process = require("child_process");
|
||||
const childProcess = require("child_process");
|
||||
|
||||
const ROOT_DIR = path.resolve(__dirname, "../");
|
||||
const MOC_AUTOGEN_DIR = path.resolve(ROOT_DIR, "src/cpp/autogen");
|
||||
@ -53,7 +53,7 @@ const main = () => {
|
||||
includeFilePath
|
||||
);
|
||||
console.log(command);
|
||||
process.exec(command, error => {
|
||||
childProcess.exec(command, {}, error => {
|
||||
if (error) {
|
||||
console.error(`exec error: ${error}`);
|
||||
return;
|
||||
|
||||
@ -57,7 +57,12 @@ Napi::Value setStyleSheet(const Napi::CallbackInfo& info){ \
|
||||
this->instance->setStyleSheet(style.c_str()); \
|
||||
return env.Null(); \
|
||||
} \
|
||||
\
|
||||
Napi::Value styleSheet(const Napi::CallbackInfo& info){ \
|
||||
Napi::Env env = info.Env(); \
|
||||
Napi::HandleScope scope(env); \
|
||||
QString stylesheet = this->instance->styleSheet(); \
|
||||
return Napi::String::New(env, stylesheet.toStdString()); \
|
||||
} \
|
||||
Napi::Value hide(const Napi::CallbackInfo& info) { \
|
||||
Napi::Env env = info.Env(); \
|
||||
Napi::HandleScope scope(env); \
|
||||
@ -72,6 +77,12 @@ Napi::Value setObjectName(const Napi::CallbackInfo& info){ \
|
||||
this->instance->setObjectName(QString::fromStdString(objectName.Utf8Value())); \
|
||||
return env.Null(); \
|
||||
} \
|
||||
Napi::Value objectName(const Napi::CallbackInfo& info){ \
|
||||
Napi::Env env = info.Env(); \
|
||||
Napi::HandleScope scope(env); \
|
||||
QString objectName = this->instance->objectName(); \
|
||||
return Napi::String::New(env, objectName.toStdString()); \
|
||||
} \
|
||||
Napi::Value setMouseTracking(const Napi::CallbackInfo& info){ \
|
||||
Napi::Env env = info.Env(); \
|
||||
Napi::HandleScope scope(env); \
|
||||
@ -137,6 +148,21 @@ Napi::Value size(const Napi::CallbackInfo& info){ \
|
||||
sizeObj.Set("height", size.height()); \
|
||||
return sizeObj; \
|
||||
} \
|
||||
Napi::Value setAttribute(const Napi::CallbackInfo& info){ \
|
||||
Napi::Env env = info.Env(); \
|
||||
Napi::HandleScope scope(env); \
|
||||
int attributeId = info[0].As<Napi::Number>().Int32Value(); \
|
||||
bool switchOn = info[1].As<Napi::Boolean>().Value(); \
|
||||
this->instance->setAttribute(static_cast<Qt::WidgetAttribute>(attributeId), switchOn); \
|
||||
return env.Null(); \
|
||||
} \
|
||||
Napi::Value testAttribute(const Napi::CallbackInfo& info){ \
|
||||
Napi::Env env = info.Env(); \
|
||||
Napi::HandleScope scope(env); \
|
||||
int attributeId = info[0].As<Napi::Number>().Int32Value(); \
|
||||
bool isOn = this->instance->testAttribute(static_cast<Qt::WidgetAttribute>(attributeId)); \
|
||||
return Napi::Boolean::New(env, isOn); \
|
||||
} \
|
||||
|
||||
#endif //QWIDGET_WRAPPED_METHODS_DECLARATION
|
||||
|
||||
@ -151,8 +177,10 @@ Napi::Value size(const Napi::CallbackInfo& info){ \
|
||||
InstanceMethod("close",&WidgetWrapName::close), \
|
||||
InstanceMethod("setLayout",&WidgetWrapName::setLayout), \
|
||||
InstanceMethod("setStyleSheet",&WidgetWrapName::setStyleSheet), \
|
||||
InstanceMethod("styleSheet",&WidgetWrapName::styleSheet), \
|
||||
InstanceMethod("hide",&WidgetWrapName::hide), \
|
||||
InstanceMethod("setObjectName",&WidgetWrapName::setObjectName), \
|
||||
InstanceMethod("objectName",&WidgetWrapName::objectName), \
|
||||
InstanceMethod("setMouseTracking",&WidgetWrapName::setMouseTracking), \
|
||||
InstanceMethod("setEnabled",&WidgetWrapName::setEnabled), \
|
||||
InstanceMethod("setFixedSize",&WidgetWrapName::setFixedSize), \
|
||||
@ -162,5 +190,7 @@ Napi::Value size(const Napi::CallbackInfo& info){ \
|
||||
InstanceMethod("update",&WidgetWrapName::update), \
|
||||
InstanceMethod("updateGeometry",&WidgetWrapName::updateGeometry), \
|
||||
InstanceMethod("size",&WidgetWrapName::size), \
|
||||
InstanceMethod("setAttribute",&WidgetWrapName::setAttribute), \
|
||||
InstanceMethod("testAttribute",&WidgetWrapName::testAttribute), \
|
||||
|
||||
#endif // QWIDGET_WRAPPED_METHODS_EXPORT_DEFINE
|
||||
|
||||
@ -22,7 +22,6 @@ NWidget* QWidgetWrap::getInternalInstance() {
|
||||
QWidgetWrap::QWidgetWrap(const Napi::CallbackInfo& info): Napi::ObjectWrap<QWidgetWrap>(info) {
|
||||
Napi::Env env = info.Env();
|
||||
Napi::HandleScope scope(env);
|
||||
|
||||
if(info.Length() == 1) {
|
||||
Napi::Object parentObject = info[0].As<Napi::Object>();
|
||||
QWidgetWrap* parentWidgetWrap = Napi::ObjectWrap<QWidgetWrap>::Unwrap(parentObject);
|
||||
|
||||
@ -3,3 +3,89 @@ export enum AspectRatioMode {
|
||||
"KeepAspectRatio",
|
||||
"KeepAspectRatioByExpanding"
|
||||
}
|
||||
|
||||
export enum WidgetAttribute {
|
||||
WA_AcceptDrops = 78,
|
||||
WA_AlwaysShowToolTips = 84,
|
||||
WA_ContentsPropagated = 3,
|
||||
WA_CustomWhatsThis = 47,
|
||||
WA_DeleteOnClose = 55,
|
||||
WA_Disabled = 0,
|
||||
WA_DontShowOnScreen = 103,
|
||||
WA_ForceDisabled = 32,
|
||||
WA_ForceUpdatesDisabled = 59,
|
||||
WA_GroupLeader = 72,
|
||||
WA_Hover = 74,
|
||||
WA_InputMethodEnabled = 14,
|
||||
WA_KeyboardFocusChange = 77,
|
||||
WA_KeyCompression = 33,
|
||||
WA_LayoutOnEntireRect = 48,
|
||||
WA_LayoutUsesWidgetRect = 92,
|
||||
WA_MacNoClickThrough = 12,
|
||||
WA_MacOpaqueSizeGrip = 85,
|
||||
WA_MacShowFocusRect = 88,
|
||||
WA_MacNormalSize = 89,
|
||||
WA_MacSmallSize = 90,
|
||||
WA_MacMiniSize = 91,
|
||||
WA_MacVariableSize = 102,
|
||||
WA_MacBrushedMetal = 46,
|
||||
WA_Mapped = 11,
|
||||
WA_MouseNoMask = 71,
|
||||
WA_MouseTracking = 2,
|
||||
WA_Moved = 43,
|
||||
WA_MSWindowsUseDirect3D = 94,
|
||||
WA_NoChildEventsForParent = 58,
|
||||
WA_NoChildEventsFromChildren = 39,
|
||||
WA_NoMouseReplay = 54,
|
||||
WA_NoMousePropagation = 73,
|
||||
WA_TransparentForMouseEvents = 51,
|
||||
WA_NoSystemBackground = 9,
|
||||
WA_OpaquePaintEvent = 4,
|
||||
WA_OutsideWSRange = 49,
|
||||
WA_PaintOnScreen = 8,
|
||||
WA_PaintUnclipped = 52,
|
||||
WA_PendingMoveEvent = 34,
|
||||
WA_PendingResizeEvent = 35,
|
||||
WA_QuitOnClose = 76,
|
||||
WA_Resized = 42,
|
||||
WA_RightToLeft = 56,
|
||||
WA_SetCursor = 38,
|
||||
WA_SetFont = 37,
|
||||
WA_SetPalette = 36,
|
||||
WA_SetStyle = 86,
|
||||
WA_ShowModal = 70,
|
||||
WA_StaticContents = 5,
|
||||
WA_StyleSheet = 97,
|
||||
WA_StyleSheetTarget = 131,
|
||||
WA_TabletTracking = 129,
|
||||
WA_TranslucentBackground = 120,
|
||||
WA_UnderMouse = 1,
|
||||
WA_UpdatesDisabled = 10,
|
||||
WA_WindowModified = 41,
|
||||
WA_WindowPropagation = 80,
|
||||
WA_MacAlwaysShowToolWindow = 96,
|
||||
WA_SetLocale = 87,
|
||||
WA_StyledBackground = 93,
|
||||
WA_ShowWithoutActivating = 98,
|
||||
WA_NativeWindow = 100,
|
||||
WA_DontCreateNativeAncestors = 101,
|
||||
WA_X11NetWmWindowTypeDesktop = 104,
|
||||
WA_X11NetWmWindowTypeDock = 105,
|
||||
WA_X11NetWmWindowTypeToolBar = 106,
|
||||
WA_X11NetWmWindowTypeMenu = 107,
|
||||
WA_X11NetWmWindowTypeUtility = 108,
|
||||
WA_X11NetWmWindowTypeSplash = 109,
|
||||
WA_X11NetWmWindowTypeDialog = 110,
|
||||
WA_X11NetWmWindowTypeDropDownMenu = 111,
|
||||
WA_X11NetWmWindowTypePopupMenu = 112,
|
||||
WA_X11NetWmWindowTypeToolTip = 113,
|
||||
WA_X11NetWmWindowTypeNotification = 114,
|
||||
WA_X11NetWmWindowTypeCombo = 115,
|
||||
WA_X11NetWmWindowTypeDND = 116,
|
||||
WA_MacFrameworkScaled = 117,
|
||||
WA_AcceptTouchEvents = 121,
|
||||
WA_TouchPadAcceptSingleTouchEvents = 123,
|
||||
WA_X11DoNotAcceptFocus = 126,
|
||||
WA_AlwaysStackOnTop = 128,
|
||||
WA_ContentsMarginsRespectsSafeArea = 13
|
||||
}
|
||||
|
||||
@ -3,11 +3,17 @@ import { NodeLayout } from "../../QtWidgets/QLayout";
|
||||
import { EventWidget, BaseWidgetEvents } from "../../core/EventWidget";
|
||||
import { NativeElement } from "../../core/Component";
|
||||
import { FlexLayout } from "../../core/FlexLayout";
|
||||
import { WidgetAttribute } from "../../QtEnums";
|
||||
import {
|
||||
applyStyleSheet,
|
||||
StyleSheet,
|
||||
prepareInlineStyleSheet
|
||||
} from "../../core/Style/StyleSheet";
|
||||
// All Widgets should extend from NodeWidget
|
||||
// Implement all native QWidget methods here so that all widgets get access to those aswell
|
||||
export abstract class NodeWidget extends EventWidget {
|
||||
type = "widget";
|
||||
layout?: NodeLayout;
|
||||
type: string = "widget";
|
||||
show = () => {
|
||||
this.native.show();
|
||||
};
|
||||
@ -26,14 +32,16 @@ export abstract class NodeWidget extends EventWidget {
|
||||
this.native.setLayout(parentLayout.native);
|
||||
this.layout = parentLayout;
|
||||
};
|
||||
setStyleSheet = async (style: string | Promise<string>) => {
|
||||
this.native.setStyleSheet(await style);
|
||||
setTimeout(() => {
|
||||
if (this.layout) {
|
||||
this.layout.invalidate(); // Hackfix: To trigger recalculation
|
||||
this.layout.update();
|
||||
}
|
||||
}, 20);
|
||||
setStyleSheet = async (styleSheet: string) => {
|
||||
const preparedSheet = await StyleSheet.create(styleSheet);
|
||||
await applyStyleSheet(this, preparedSheet);
|
||||
};
|
||||
setInlineStyle = async (style: string) => {
|
||||
const preparedSheet = await prepareInlineStyleSheet(this, style);
|
||||
await applyStyleSheet(this, preparedSheet);
|
||||
};
|
||||
styleSheet = (): string => {
|
||||
return this.native.styleSheet();
|
||||
};
|
||||
hide = () => {
|
||||
this.native.hide();
|
||||
@ -41,6 +49,9 @@ export abstract class NodeWidget extends EventWidget {
|
||||
setObjectName = (objectName: string) => {
|
||||
this.native.setObjectName(objectName);
|
||||
};
|
||||
objectName = (): string => {
|
||||
return this.native.objectName();
|
||||
};
|
||||
setMouseTracking = (isMouseTracked: boolean) => {
|
||||
this.native.setMouseTracking(isMouseTracked);
|
||||
};
|
||||
@ -68,6 +79,12 @@ export abstract class NodeWidget extends EventWidget {
|
||||
size = (): { width: number; height: number } => {
|
||||
return this.native.size();
|
||||
};
|
||||
setAttribute = (attribute: WidgetAttribute, switchOn: boolean) => {
|
||||
return this.native.setAttribute(attribute, switchOn);
|
||||
};
|
||||
testAttribute = (attribute: WidgetAttribute): boolean => {
|
||||
return this.native.testAttribute(attribute);
|
||||
};
|
||||
}
|
||||
|
||||
export class QWidget extends NodeWidget {
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import postcss from "postcss";
|
||||
import autoprefixer from "postcss-nodegui-autoprefixer";
|
||||
|
||||
import cuid from "cuid";
|
||||
import nodeguiAutoPrefixer from "postcss-nodegui-autoprefixer";
|
||||
import { NodeWidget } from "../../QtGui/QWidget";
|
||||
export class StyleSheet {
|
||||
static create = async (cssString: string): Promise<string> => {
|
||||
const { css } = await postcss([autoprefixer()])
|
||||
.process(cssString, {
|
||||
from: undefined
|
||||
})
|
||||
const { css } = await postcss([nodeguiAutoPrefixer()])
|
||||
.process(cssString, { from: undefined })
|
||||
.catch(err => {
|
||||
console.warn(`Error autoprefixing`, err);
|
||||
return { css: cssString };
|
||||
@ -14,3 +13,32 @@ export class StyleSheet {
|
||||
return css;
|
||||
};
|
||||
}
|
||||
|
||||
export const prepareInlineStyleSheet = async (
|
||||
widget: NodeWidget,
|
||||
rawStyle: string
|
||||
) => {
|
||||
const inlineStyle = await StyleSheet.create(rawStyle);
|
||||
// Make sure to not calculate ObjectName is the same pass of event loop as other props (incase of react) since the order will matter in that case
|
||||
// So doing it in multiple passes of event loop allows objectName to be set before using it. The above await solves it.
|
||||
let cssId = widget.objectName();
|
||||
if (!cssId) {
|
||||
cssId = cuid();
|
||||
widget.setObjectName(cssId);
|
||||
}
|
||||
return `
|
||||
#${cssId} {
|
||||
${inlineStyle}
|
||||
}
|
||||
`;
|
||||
};
|
||||
|
||||
export const applyStyleSheet = async (
|
||||
widget: NodeWidget,
|
||||
styleSheet: string
|
||||
) => {
|
||||
widget.native.setStyleSheet(styleSheet);
|
||||
setTimeout(() => {
|
||||
widget.layout ? widget.layout.update() : widget.update();
|
||||
}, 20);
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user