cedro 0.1.3 → 0.1.4
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/package.json +1 -1
- package/src/interfaces/widget.interface.ts +6 -1
- package/src/types/orientation.type.ts +1 -0
- package/src/ui/datagrid.ui.ts +216 -0
- package/src/ui/draggable.ui.ts +143 -0
- package/src/ui/index.ts +17 -1
- package/src/ui/scroll.ui.ts +185 -0
- package/src/ui/styles/datagrid.css +10 -0
- package/src/ui/styles/draggable.css +9 -0
- package/src/ui/styles/scroll.css +4 -0
- package/src/ui/styles/tabs.css +33 -0
- package/src/ui/tabs.ui.ts +131 -0
- package/src/ui/toolbar.ui.ts +4 -4
- package/src/ui/widget.ui.ts +35 -1
package/package.json
CHANGED
|
@@ -7,7 +7,11 @@ export type WUIEvent =
|
|
|
7
7
|
| "mousedown"
|
|
8
8
|
| "mouseup"
|
|
9
9
|
| "mousemove"
|
|
10
|
-
| "
|
|
10
|
+
| "mouseout"
|
|
11
|
+
| "mouseleave"
|
|
12
|
+
| "option-clicked"
|
|
13
|
+
| "wheel"
|
|
14
|
+
| "drag";
|
|
11
15
|
|
|
12
16
|
export type WUICallback = {
|
|
13
17
|
event: WUIEvent;
|
|
@@ -48,6 +52,7 @@ export interface IWidget {
|
|
|
48
52
|
|
|
49
53
|
subscribe: (cb: WUICallback) => void;
|
|
50
54
|
unsubscribe: (event: WUIEvent) => void;
|
|
55
|
+
run(eventId: WUIEvent): void;
|
|
51
56
|
|
|
52
57
|
setPadding(p: number): void;
|
|
53
58
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type OrientationTypes = "horizontal" | "vertical";
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import "./styles/datagrid.css";
|
|
2
|
+
import { Label } from "./label.ui";
|
|
3
|
+
import { Widget, WidgetAlignTypes, WidgetTypes } from "./widget.ui";
|
|
4
|
+
import { Scroll } from "./scroll.ui";
|
|
5
|
+
|
|
6
|
+
const DATA_GRID_HEADER_HEIGHT = 30;
|
|
7
|
+
const DATA_GRID_FOOTER_HEIGHT = 40;
|
|
8
|
+
const DATA_GRID_ROW_HEIGHT = 20;
|
|
9
|
+
const DATA_GRID_MIN_COLUMN_WIDTH = 24;
|
|
10
|
+
|
|
11
|
+
type DataGridColumn = {
|
|
12
|
+
header: string;
|
|
13
|
+
width: number | null;
|
|
14
|
+
handler: (args: any) => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export class DataGrid extends Widget {
|
|
18
|
+
headerContainer: Widget;
|
|
19
|
+
dataContainer: Widget;
|
|
20
|
+
footerContainer: Widget;
|
|
21
|
+
data: Array<any>;
|
|
22
|
+
verticalScrollbar: Scroll;
|
|
23
|
+
horizontalScrollbar: Scroll;
|
|
24
|
+
|
|
25
|
+
rowHeight: number;
|
|
26
|
+
|
|
27
|
+
columns: Array<DataGridColumn>;
|
|
28
|
+
|
|
29
|
+
constructor(id: string, parent: Widget | null = null) {
|
|
30
|
+
super(id, "div", parent);
|
|
31
|
+
|
|
32
|
+
this.rowHeight = DATA_GRID_ROW_HEIGHT;
|
|
33
|
+
|
|
34
|
+
this.headerContainer = new Widget(id + ".header", "div");
|
|
35
|
+
this.headerContainer.setType(WidgetTypes.FILL);
|
|
36
|
+
this.headerContainer.setFixedSize(DATA_GRID_HEADER_HEIGHT);
|
|
37
|
+
this.headerContainer.addClass("WUIDataGrid-Header");
|
|
38
|
+
|
|
39
|
+
this.dataContainer = new Widget(id + ".data", "div");
|
|
40
|
+
this.dataContainer.setType(WidgetTypes.FILL);
|
|
41
|
+
|
|
42
|
+
this.footerContainer = new Widget(id + ".footer", "div");
|
|
43
|
+
this.footerContainer.setType(WidgetTypes.FILL);
|
|
44
|
+
this.footerContainer.setFixedSize(DATA_GRID_FOOTER_HEIGHT);
|
|
45
|
+
|
|
46
|
+
this.setType(WidgetTypes.FILL);
|
|
47
|
+
this.setAlign(WidgetAlignTypes.VERTICAL);
|
|
48
|
+
|
|
49
|
+
this.addChild(this.headerContainer);
|
|
50
|
+
this.addChild(this.dataContainer);
|
|
51
|
+
this.addChild(this.footerContainer);
|
|
52
|
+
|
|
53
|
+
this.verticalScrollbar = new Scroll(id + ".VerticalScrollbar", this.dataContainer);
|
|
54
|
+
this.horizontalScrollbar = new Scroll(id + ".HorizontalScrollbar", this.dataContainer, "horizontal");
|
|
55
|
+
|
|
56
|
+
this.columns = new Array<DataGridColumn>();
|
|
57
|
+
|
|
58
|
+
this.data = new Array<any>();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private getFreeWidth(): number {
|
|
62
|
+
let freeW = 0;
|
|
63
|
+
for (let i = 0; i < this.columns.length; i++) {
|
|
64
|
+
let width = this.columns[i].width;
|
|
65
|
+
if (width) {
|
|
66
|
+
freeW += width;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
freeW = this.dataContainer.getW() - freeW;
|
|
71
|
+
|
|
72
|
+
if (freeW < DATA_GRID_MIN_COLUMN_WIDTH) {
|
|
73
|
+
freeW = DATA_GRID_MIN_COLUMN_WIDTH;
|
|
74
|
+
}
|
|
75
|
+
return freeW;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private getAllColumnsWidth(): number {
|
|
79
|
+
let returnValue = 0;
|
|
80
|
+
for (let i = 0; i < this.columns.length; i++) {
|
|
81
|
+
let width = this.columns[i].width;
|
|
82
|
+
if (width) {
|
|
83
|
+
returnValue += width;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return returnValue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public init(): void {
|
|
90
|
+
super.init();
|
|
91
|
+
|
|
92
|
+
this.createHeaders();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private createHeaders(): void {
|
|
96
|
+
if (!this.columns) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
for (let i = 0; i < this.columns.length; i++) {
|
|
101
|
+
const btn = new Label(this.id + "header." + i, "span");
|
|
102
|
+
btn.addClass("WUIDataGrid-HeaderLabel");
|
|
103
|
+
this.headerContainer.addChild(btn);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.buildRows();
|
|
107
|
+
this.renderHeaders();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private renderHeaders(): void {
|
|
111
|
+
if (!this.columns) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let startX = 0;
|
|
116
|
+
for (let i = 0; i < this.columns.length; i++) {
|
|
117
|
+
const column = this.columns[i];
|
|
118
|
+
const btn = window.w.get(this.id + "header." + i) as Label;
|
|
119
|
+
const width = column.width ? column.width : this.getFreeWidth();
|
|
120
|
+
btn.setType(WidgetTypes.CUSTOM);
|
|
121
|
+
btn.setX(startX);
|
|
122
|
+
btn.setY(0);
|
|
123
|
+
btn.setW(width);
|
|
124
|
+
btn.setH(DATA_GRID_HEADER_HEIGHT);
|
|
125
|
+
btn.getBody().style.lineHeight = DATA_GRID_HEADER_HEIGHT + "px";
|
|
126
|
+
btn.setText(column.header);
|
|
127
|
+
this.headerContainer.addChild(btn);
|
|
128
|
+
startX += width;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private buildRows(): void {
|
|
133
|
+
let rowY = 0;
|
|
134
|
+
|
|
135
|
+
for (let i = 0; i < this.data.length; i++) {
|
|
136
|
+
const row = new Widget(this.id + ".row." + i, "div");
|
|
137
|
+
|
|
138
|
+
row.setType(WidgetTypes.CUSTOM);
|
|
139
|
+
row.getBody().style.position = "absolute";
|
|
140
|
+
row.getBody().style.overflow = "hidden";
|
|
141
|
+
|
|
142
|
+
this.dataContainer.addChild(row);
|
|
143
|
+
|
|
144
|
+
for (let j = 0; j < this.columns.length; j++) {
|
|
145
|
+
const column = this.columns[j];
|
|
146
|
+
const fieldId = this.id + ".row." + i + ".column." + j;
|
|
147
|
+
column.handler({
|
|
148
|
+
data: this.data[i],
|
|
149
|
+
index: i,
|
|
150
|
+
fieldId: fieldId,
|
|
151
|
+
row: row,
|
|
152
|
+
});
|
|
153
|
+
const columnWidget = window.w.get(fieldId) as Widget;
|
|
154
|
+
columnWidget.getBody().style.position = "absolute";
|
|
155
|
+
}
|
|
156
|
+
rowY += this.rowHeight;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private renderRows(): void {
|
|
161
|
+
let rowY = 0;
|
|
162
|
+
|
|
163
|
+
for (let i = 0; i < this.data.length; i++) {
|
|
164
|
+
const row = window.w.get(this.id + ".row." + i) as Widget;
|
|
165
|
+
|
|
166
|
+
row.setX(0);
|
|
167
|
+
row.setY(rowY);
|
|
168
|
+
row.setW(this.getAllColumnsWidth());
|
|
169
|
+
row.setH(this.rowHeight);
|
|
170
|
+
|
|
171
|
+
let widgetX = 0;
|
|
172
|
+
for (let j = 0; j < this.columns.length; j++) {
|
|
173
|
+
const column = this.columns[j];
|
|
174
|
+
const fieldId = this.id + ".row." + i + ".column." + j;
|
|
175
|
+
const columnWidget = window.w.get(fieldId) as Widget;
|
|
176
|
+
columnWidget.setY(0);
|
|
177
|
+
columnWidget.setX(widgetX);
|
|
178
|
+
columnWidget.setH(this.rowHeight);
|
|
179
|
+
if (column.width) {
|
|
180
|
+
columnWidget.setW(column.width);
|
|
181
|
+
} else {
|
|
182
|
+
columnWidget.setW(this.getFreeWidth());
|
|
183
|
+
}
|
|
184
|
+
widgetX += column.width ? column.width : columnWidget.getW();
|
|
185
|
+
}
|
|
186
|
+
rowY += this.rowHeight;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public render(): void {
|
|
191
|
+
super.render();
|
|
192
|
+
this.renderHeaders();
|
|
193
|
+
this.renderRows();
|
|
194
|
+
this.verticalScrollbar.render();
|
|
195
|
+
this.horizontalScrollbar.render();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public setRowHeight(rowHeight: number): void {
|
|
199
|
+
this.rowHeight = rowHeight;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public addColumn(header: string, width: number | null, handler: (args: any) => void) {
|
|
203
|
+
this.columns.push({ header, width, handler });
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
public getHeader(index: number): Label {
|
|
207
|
+
return window.w.get(this.id + "header." + index) as Label;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
public setData(data: Array<any>): void {
|
|
211
|
+
this.data = data;
|
|
212
|
+
|
|
213
|
+
this.buildRows();
|
|
214
|
+
this.renderRows();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { OrientationTypes } from "src/types/orientation.type";
|
|
2
|
+
import "./styles/draggable.css";
|
|
3
|
+
import { Widget, WidgetTypes } from "./widget.ui";
|
|
4
|
+
|
|
5
|
+
export type DragOrientation = OrientationTypes | "both";
|
|
6
|
+
|
|
7
|
+
export class Draggable {
|
|
8
|
+
target: Widget;
|
|
9
|
+
background: Widget;
|
|
10
|
+
|
|
11
|
+
dragging: boolean = false;
|
|
12
|
+
dragDistX: number;
|
|
13
|
+
dragDistY: number;
|
|
14
|
+
dragOrientation: DragOrientation;
|
|
15
|
+
|
|
16
|
+
minX: number | null;
|
|
17
|
+
minY: number | null;
|
|
18
|
+
maxX: number | null;
|
|
19
|
+
maxY: number | null;
|
|
20
|
+
|
|
21
|
+
constructor(widget: Widget, orientation: DragOrientation = "both") {
|
|
22
|
+
this.target = widget;
|
|
23
|
+
|
|
24
|
+
this.background = new Widget(this.target.id + ".Draggable.Background", "div", null);
|
|
25
|
+
this.background.setType(WidgetTypes.CUSTOM);
|
|
26
|
+
this.background.addClass("WUIDraggableBackground");
|
|
27
|
+
|
|
28
|
+
this.dragDistX = 0;
|
|
29
|
+
this.dragDistY = 0;
|
|
30
|
+
|
|
31
|
+
this.maxX = null;
|
|
32
|
+
this.maxY = null;
|
|
33
|
+
|
|
34
|
+
this.minX = null;
|
|
35
|
+
this.minY = null;
|
|
36
|
+
|
|
37
|
+
this.dragOrientation = orientation;
|
|
38
|
+
|
|
39
|
+
this.target.subscribe({
|
|
40
|
+
event: "mousedown",
|
|
41
|
+
then: (e, _w) => {
|
|
42
|
+
this.startDrag(e as MouseEvent);
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.background.subscribe({
|
|
47
|
+
event: "mousemove",
|
|
48
|
+
then: (e, _w) => {
|
|
49
|
+
this.draggingTarget(e as MouseEvent);
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
this.background.subscribe({
|
|
54
|
+
event: "mouseup",
|
|
55
|
+
then: (_e, _w) => {
|
|
56
|
+
this.endDrag();
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
this.background.subscribe({
|
|
61
|
+
event: "mouseout",
|
|
62
|
+
then: (_e, _w) => {
|
|
63
|
+
this.endDrag();
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
this.background.subscribe({
|
|
68
|
+
event: "mouseleave",
|
|
69
|
+
then: (_e, _w) => {
|
|
70
|
+
this.endDrag();
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private startDrag(e: MouseEvent): void {
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
const mouseX = e.clientX;
|
|
78
|
+
const mouseY = e.clientY;
|
|
79
|
+
this.dragDistX = Math.abs(this.target.getX() - mouseX);
|
|
80
|
+
this.dragDistY = Math.abs(this.target.getY() - mouseY);
|
|
81
|
+
this.dragging = true;
|
|
82
|
+
this.background.setVisible(true);
|
|
83
|
+
this.background.raisteTop();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private draggingTarget(e: MouseEvent): void {
|
|
87
|
+
if (!this.dragging) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
|
|
93
|
+
const mouseX = e.clientX;
|
|
94
|
+
const mouseY = e.clientY;
|
|
95
|
+
|
|
96
|
+
if (this.dragOrientation === "both" || this.dragOrientation === "horizontal") {
|
|
97
|
+
let newX = mouseX - this.dragDistX;
|
|
98
|
+
if (this.maxX != null && newX > this.maxX) {
|
|
99
|
+
newX = this.maxX;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (this.minX != null && newX < this.minX) {
|
|
103
|
+
newX = this.minX;
|
|
104
|
+
}
|
|
105
|
+
this.target.setX(newX);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (this.dragOrientation === "both" || this.dragOrientation === "vertical") {
|
|
109
|
+
let newY = mouseY - this.dragDistY;
|
|
110
|
+
if (this.maxY != null && newY > this.maxY) {
|
|
111
|
+
newY = this.maxY;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (this.minY != null && newY < this.minY) {
|
|
115
|
+
newY = this.minY;
|
|
116
|
+
}
|
|
117
|
+
this.target.setY(newY);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.target.run("drag");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private endDrag(): void {
|
|
124
|
+
this.dragging = false;
|
|
125
|
+
this.background.setVisible(false);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public setMaxX(x: number | null): void {
|
|
129
|
+
this.maxX = x;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public setMaxY(y: number | null): void {
|
|
133
|
+
this.maxY = y;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public setMinX(x: number | null): void {
|
|
137
|
+
this.minX = x;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public setMinY(y: number | null): void {
|
|
141
|
+
this.minY = y;
|
|
142
|
+
}
|
|
143
|
+
}
|
package/src/ui/index.ts
CHANGED
|
@@ -7,7 +7,23 @@ import { Label } from "./label.ui";
|
|
|
7
7
|
import { Menu } from "./menu.ui";
|
|
8
8
|
import { Select } from "./select.ui";
|
|
9
9
|
import { Textbox } from "./textbox.ui";
|
|
10
|
+
import { Tabs } from "./tabs.ui";
|
|
10
11
|
import { Toolbar } from "./toolbar.ui";
|
|
12
|
+
import { DataGrid } from "./datagrid.ui";
|
|
11
13
|
import { createWidget } from "./widget.builder.ui";
|
|
12
14
|
|
|
13
|
-
export {
|
|
15
|
+
export {
|
|
16
|
+
Button,
|
|
17
|
+
Widget,
|
|
18
|
+
Dialog,
|
|
19
|
+
Icon,
|
|
20
|
+
IconButton,
|
|
21
|
+
Label,
|
|
22
|
+
Menu,
|
|
23
|
+
Select,
|
|
24
|
+
Tabs,
|
|
25
|
+
Textbox,
|
|
26
|
+
Toolbar,
|
|
27
|
+
DataGrid,
|
|
28
|
+
createWidget,
|
|
29
|
+
};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { OrientationTypes } from "src/types/orientation.type";
|
|
2
|
+
import "./styles/scroll.css";
|
|
3
|
+
import { Widget, WidgetTypes } from "./widget.ui";
|
|
4
|
+
import { Draggable } from "./draggable.ui";
|
|
5
|
+
|
|
6
|
+
const SCROLL_SIZE = 10;
|
|
7
|
+
|
|
8
|
+
type ScrollData = {
|
|
9
|
+
scrollHeight: number;
|
|
10
|
+
areaHeight: number;
|
|
11
|
+
scrollBarHeight: number;
|
|
12
|
+
scrollWidth: number;
|
|
13
|
+
areaWidth: number;
|
|
14
|
+
scrollBarWidth: number;
|
|
15
|
+
scrollWidt: number;
|
|
16
|
+
availablePositionSize: number;
|
|
17
|
+
ratioScroll: number;
|
|
18
|
+
position: number;
|
|
19
|
+
scrollPositionY: number;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export class Scroll extends Widget {
|
|
23
|
+
contentArea: Widget;
|
|
24
|
+
orientation: OrientationTypes;
|
|
25
|
+
|
|
26
|
+
drag: Draggable;
|
|
27
|
+
|
|
28
|
+
constructor(id: string, contentArea: Widget, orientation: OrientationTypes = "vertical") {
|
|
29
|
+
super(id, "div", contentArea.getParent());
|
|
30
|
+
|
|
31
|
+
this.contentArea = contentArea;
|
|
32
|
+
this.orientation = orientation;
|
|
33
|
+
|
|
34
|
+
this.setType(WidgetTypes.CUSTOM);
|
|
35
|
+
|
|
36
|
+
this.getBody().style.overflow = "hidden";
|
|
37
|
+
this.getBody().style.position = "absolute";
|
|
38
|
+
|
|
39
|
+
this.addClass("WUIScrollbar");
|
|
40
|
+
|
|
41
|
+
this.drag = new Draggable(this, orientation);
|
|
42
|
+
|
|
43
|
+
this.contentArea.subscribe({
|
|
44
|
+
event: "wheel",
|
|
45
|
+
then: (e, _w) => {
|
|
46
|
+
const wheel = e as WheelEvent;
|
|
47
|
+
this.contentArea.getBody().scrollBy(0, wheel.deltaY);
|
|
48
|
+
this.render();
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
this.subscribe({
|
|
53
|
+
event: "drag",
|
|
54
|
+
then: (_e, _w) => {
|
|
55
|
+
this.updateScrollPositionByScrollbar();
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private getScrollData(): ScrollData {
|
|
61
|
+
let returnData: ScrollData = {
|
|
62
|
+
scrollHeight: 0,
|
|
63
|
+
areaHeight: 0,
|
|
64
|
+
scrollBarHeight: 0,
|
|
65
|
+
scrollWidth: 0,
|
|
66
|
+
areaWidth: 0,
|
|
67
|
+
scrollBarWidth: 0,
|
|
68
|
+
scrollWidt: 0,
|
|
69
|
+
availablePositionSize: 0,
|
|
70
|
+
ratioScroll: 0,
|
|
71
|
+
position: 0,
|
|
72
|
+
scrollPositionY: 0,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
if (this.orientation === "vertical") {
|
|
76
|
+
returnData.scrollHeight = this.contentArea.getBody().scrollHeight;
|
|
77
|
+
returnData.areaHeight = this.contentArea.getH();
|
|
78
|
+
returnData.scrollBarHeight =
|
|
79
|
+
returnData.areaHeight * (returnData.areaHeight / returnData.scrollHeight);
|
|
80
|
+
returnData.availablePositionSize =
|
|
81
|
+
returnData.areaHeight - returnData.scrollBarHeight - 1;
|
|
82
|
+
returnData.ratioScroll =
|
|
83
|
+
this.contentArea.getBody().scrollTop /
|
|
84
|
+
(returnData.areaHeight - returnData.scrollBarHeight);
|
|
85
|
+
returnData.position = returnData.availablePositionSize * returnData.ratioScroll;
|
|
86
|
+
|
|
87
|
+
if (returnData.scrollBarHeight >= returnData.areaHeight) {
|
|
88
|
+
returnData.scrollBarHeight = returnData.areaHeight;
|
|
89
|
+
}
|
|
90
|
+
} else if (this.orientation === "horizontal") {
|
|
91
|
+
returnData.scrollWidth = this.contentArea.getBody().scrollWidth;
|
|
92
|
+
returnData.areaWidth = this.contentArea.getW();
|
|
93
|
+
returnData.scrollBarWidth =
|
|
94
|
+
returnData.areaWidth * (returnData.areaWidth / returnData.scrollWidth);
|
|
95
|
+
returnData.availablePositionSize = returnData.areaWidth - returnData.scrollBarWidth - 1;
|
|
96
|
+
returnData.ratioScroll =
|
|
97
|
+
this.contentArea.getBody().scrollLeft /
|
|
98
|
+
(returnData.areaWidth - returnData.scrollBarWidth);
|
|
99
|
+
returnData.position = returnData.availablePositionSize * returnData.ratioScroll;
|
|
100
|
+
returnData.scrollPositionY = this.contentArea.getH() + this.contentArea.getY();
|
|
101
|
+
if (returnData.scrollBarWidth >= returnData.areaWidth) {
|
|
102
|
+
returnData.scrollBarWidth = returnData.areaWidth;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return returnData;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private updateScrollPositionByScrollbar(): void {
|
|
109
|
+
const scrollData = this.getScrollData();
|
|
110
|
+
|
|
111
|
+
if (this.orientation === "vertical") {
|
|
112
|
+
const recorrido = scrollData.scrollHeight - scrollData.areaHeight;
|
|
113
|
+
const maxY = this.drag.maxY ? this.drag.maxY : 1;
|
|
114
|
+
const ratio = (this.getY() - this.contentArea.getY()) / maxY;
|
|
115
|
+
this.contentArea.getBody().scrollTop = recorrido * ratio;
|
|
116
|
+
} else if (this.orientation === "horizontal") {
|
|
117
|
+
const recorrido = scrollData.scrollWidth - scrollData.areaWidth;
|
|
118
|
+
const maxX = this.drag.maxX ? this.drag.maxX : 1;
|
|
119
|
+
const ratio = (this.getX() - this.contentArea.getX()) / maxX;
|
|
120
|
+
this.contentArea.getBody().scrollLeft = recorrido * ratio;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public render(): void {
|
|
125
|
+
super.render();
|
|
126
|
+
|
|
127
|
+
const scrollData = this.getScrollData();
|
|
128
|
+
|
|
129
|
+
if (this.orientation === "vertical") {
|
|
130
|
+
if (scrollData.areaHeight < scrollData.scrollHeight) {
|
|
131
|
+
this.setVisible(true);
|
|
132
|
+
} else {
|
|
133
|
+
this.setVisible(false);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this.setX(this.contentArea.getW() - SCROLL_SIZE - 1);
|
|
138
|
+
this.setY(1 + this.contentArea.getY() + scrollData.position);
|
|
139
|
+
this.setH(scrollData.scrollBarHeight);
|
|
140
|
+
this.setW(SCROLL_SIZE);
|
|
141
|
+
this.raisteTop();
|
|
142
|
+
|
|
143
|
+
const minY = 1 + this.contentArea.getY();
|
|
144
|
+
const maxY = this.contentArea.getY() + scrollData.availablePositionSize;
|
|
145
|
+
|
|
146
|
+
this.drag.setMinY(minY);
|
|
147
|
+
this.drag.setMaxY(maxY);
|
|
148
|
+
|
|
149
|
+
if (this.getY() > maxY) {
|
|
150
|
+
this.setY(maxY);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (this.getY() < minY) {
|
|
154
|
+
this.setY(minY);
|
|
155
|
+
}
|
|
156
|
+
} else if (this.orientation === "horizontal") {
|
|
157
|
+
if (scrollData.areaWidth < scrollData.scrollWidth) {
|
|
158
|
+
this.setVisible(true);
|
|
159
|
+
} else {
|
|
160
|
+
this.setVisible(false);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
this.setX(1 + this.contentArea.getX() + scrollData.position);
|
|
165
|
+
this.setY(scrollData.scrollPositionY - SCROLL_SIZE - 1);
|
|
166
|
+
this.setW(scrollData.scrollBarWidth);
|
|
167
|
+
this.setH(SCROLL_SIZE);
|
|
168
|
+
this.raisteTop();
|
|
169
|
+
|
|
170
|
+
const minX = 1 + this.contentArea.getX();
|
|
171
|
+
const maxX = this.contentArea.getX() + scrollData.availablePositionSize;
|
|
172
|
+
|
|
173
|
+
this.drag.setMinX(minX);
|
|
174
|
+
this.drag.setMaxX(maxX);
|
|
175
|
+
|
|
176
|
+
if (this.getX() > maxX) {
|
|
177
|
+
this.setX(maxX);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (this.getX() < minX) {
|
|
181
|
+
this.setX(minX);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
.WUIDataGrid-Header {
|
|
2
|
+
border-bottom: solid 1px var(--palette-primary-text-light);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.WUIDataGrid-HeaderLabel {
|
|
6
|
+
border-right: solid 1px var(--palette-primary-text-light);
|
|
7
|
+
/*border-bottom: solid 1px var(--palette-primary-text-light);*/
|
|
8
|
+
padding-left: 5px;
|
|
9
|
+
font-weight: bold;
|
|
10
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
.WUITabControl {
|
|
2
|
+
border-top: none !important;
|
|
3
|
+
border-left: none !important;
|
|
4
|
+
border-right: none !important;
|
|
5
|
+
border-bottom: none !important;
|
|
6
|
+
background-color: var(--palette-background-default);
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
font-weight: normal;
|
|
9
|
+
text-align: center;
|
|
10
|
+
cursor: default;
|
|
11
|
+
padding-left: 15px;
|
|
12
|
+
padding-right: 15px;
|
|
13
|
+
border-radius: 0px !important;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.WUITabControlActive {
|
|
17
|
+
border-top: none !important;
|
|
18
|
+
border-left: none !important;
|
|
19
|
+
border-right: none !important;
|
|
20
|
+
border-bottom: solid 2px var(--palette-primary-dark) !important;
|
|
21
|
+
background-color: var(--palette-divider);
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
font-weight: bold;
|
|
24
|
+
text-align: center;
|
|
25
|
+
cursor: default;
|
|
26
|
+
padding-left: 15px;
|
|
27
|
+
padding-right: 15px;
|
|
28
|
+
border-radius: 0px !important;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.WUITabContainer {
|
|
32
|
+
border-top: solid 1px var(--palette-divider);
|
|
33
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import "./styles/tabs.css";
|
|
2
|
+
|
|
3
|
+
import { OrientationTypes } from "src/types/orientation.type";
|
|
4
|
+
import { Widget, WidgetAlignTypes, WidgetTypes } from "./widget.ui";
|
|
5
|
+
import { Toolbar } from "./toolbar.ui";
|
|
6
|
+
import { Label } from "./label.ui";
|
|
7
|
+
import { IconButton } from "./IconButton.ui";
|
|
8
|
+
|
|
9
|
+
const TAB_HEADER_HEIGHT = 40;
|
|
10
|
+
|
|
11
|
+
export type TabItem = {
|
|
12
|
+
title: string;
|
|
13
|
+
content: Widget;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
class TabControl extends Label {
|
|
17
|
+
constructor(id: string, parent: Widget | null = null, text: string) {
|
|
18
|
+
super(id, "span", parent);
|
|
19
|
+
this.setText(text);
|
|
20
|
+
this.addClass("WUITabControl");
|
|
21
|
+
this.getBody().style.lineHeight = TAB_HEADER_HEIGHT + "px";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class Tabs extends Widget {
|
|
25
|
+
orientation: OrientationTypes;
|
|
26
|
+
|
|
27
|
+
header: Widget;
|
|
28
|
+
content: Widget;
|
|
29
|
+
|
|
30
|
+
itemControls: Toolbar;
|
|
31
|
+
|
|
32
|
+
items: Map<string, TabItem>;
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
id: string,
|
|
36
|
+
parent: Widget | null = null,
|
|
37
|
+
orientation: OrientationTypes = "horizontal"
|
|
38
|
+
) {
|
|
39
|
+
super(id, "div", parent);
|
|
40
|
+
this.orientation = orientation;
|
|
41
|
+
|
|
42
|
+
this.header = new Widget(id + ".header", "div");
|
|
43
|
+
this.header.setType(WidgetTypes.FILL);
|
|
44
|
+
this.header.setFixedSize(TAB_HEADER_HEIGHT);
|
|
45
|
+
|
|
46
|
+
this.content = new Widget(id + ".content", "div");
|
|
47
|
+
this.content.setType(WidgetTypes.FILL);
|
|
48
|
+
this.content.addClass("WUITabContainer");
|
|
49
|
+
|
|
50
|
+
this.setType(WidgetTypes.FILL);
|
|
51
|
+
|
|
52
|
+
if (this.orientation === "horizontal") {
|
|
53
|
+
this.setAlign(WidgetAlignTypes.VERTICAL);
|
|
54
|
+
} else {
|
|
55
|
+
this.setAlign(WidgetAlignTypes.HORIZONTAL);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.addChild(this.header);
|
|
59
|
+
this.addChild(this.content);
|
|
60
|
+
|
|
61
|
+
this.items = new Map<string, TabItem>();
|
|
62
|
+
|
|
63
|
+
this.itemControls = new Toolbar(id + ".itemControls", this.header);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public setOrientation(orientation: OrientationTypes) {
|
|
67
|
+
this.orientation = orientation;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public addTab(id: string, title: string, content: Widget) {
|
|
71
|
+
this.items.set(id, { title, content });
|
|
72
|
+
|
|
73
|
+
const itemControl = new TabControl(id + ".itemControl", null, title);
|
|
74
|
+
//itemControl.setW(100);
|
|
75
|
+
itemControl.setH(TAB_HEADER_HEIGHT);
|
|
76
|
+
|
|
77
|
+
itemControl.subscribe({
|
|
78
|
+
event: "click",
|
|
79
|
+
then: (_e, _w) => {
|
|
80
|
+
this.setTab(id);
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
this.itemControls.addItem(id, itemControl);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public addIconTab(id: string, icon: string, content: Widget) {
|
|
88
|
+
this.items.set(id, { title: icon, content });
|
|
89
|
+
|
|
90
|
+
const itemControl = new IconButton(id + ".itemControl", icon);
|
|
91
|
+
itemControl.setW(40);
|
|
92
|
+
itemControl.setH(TAB_HEADER_HEIGHT);
|
|
93
|
+
|
|
94
|
+
itemControl.subscribe({
|
|
95
|
+
event: "click",
|
|
96
|
+
then: (_e, _w) => {
|
|
97
|
+
this.setTab(id);
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
this.itemControls.addItem(id, itemControl);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public setTab(id: string) {
|
|
105
|
+
this.content.removeAllChilds();
|
|
106
|
+
const actualTab = this.items.get(id);
|
|
107
|
+
|
|
108
|
+
for (const itemId of this.items.keys()) {
|
|
109
|
+
if (itemId != id) {
|
|
110
|
+
this.items.get(itemId)?.content.setVisible(false);
|
|
111
|
+
const ctrlTab = window.w.get(itemId + ".itemControl");
|
|
112
|
+
if (ctrlTab) {
|
|
113
|
+
ctrlTab.deleteClass("WUITabControlActive");
|
|
114
|
+
ctrlTab.addClass("WUITabControl");
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
const ctrlTab = window.w.get(itemId + ".itemControl");
|
|
118
|
+
if (ctrlTab) {
|
|
119
|
+
ctrlTab.addClass("WUITabControlActive");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (actualTab) {
|
|
125
|
+
this.items.get(id)?.content.setVisible(true);
|
|
126
|
+
this.content.addChild(actualTab.content);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.render();
|
|
130
|
+
}
|
|
131
|
+
}
|
package/src/ui/toolbar.ui.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { IWidget } from "src/interfaces/widget.interface";
|
|
2
2
|
import { Widget, WidgetTypes } from "./widget.ui";
|
|
3
3
|
import { IconButton } from "./IconButton.ui";
|
|
4
|
+
import { OrientationTypes } from "src/types/orientation.type";
|
|
4
5
|
|
|
5
|
-
export type ToolbarOrientationTypes = "horizontal" | "vertical";
|
|
6
6
|
const TOOLBAR_SIZE = 40;
|
|
7
7
|
const TOOLBAR_BUTTON_SIZE = 40;
|
|
8
8
|
|
|
9
9
|
export class Toolbar extends Widget {
|
|
10
|
-
orientation:
|
|
10
|
+
orientation: OrientationTypes;
|
|
11
11
|
items: Map<string, IWidget>;
|
|
12
12
|
size: number; //Indica el alto o ancho de la toolbar.
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ export class Toolbar extends Widget {
|
|
|
15
15
|
btnLeft: IconButton;
|
|
16
16
|
btnRight: IconButton;
|
|
17
17
|
|
|
18
|
-
constructor(id: string, parent: Widget | null = null, orientationType:
|
|
18
|
+
constructor(id: string, parent: Widget | null = null, orientationType: OrientationTypes = "horizontal") {
|
|
19
19
|
super(id, "div", parent);
|
|
20
20
|
this.orientation = orientationType;
|
|
21
21
|
this.size = TOOLBAR_SIZE;
|
|
@@ -86,7 +86,7 @@ export class Toolbar extends Widget {
|
|
|
86
86
|
* @param {ToolbarOrientationTypes} orientationType - the type of orientation to set
|
|
87
87
|
* @return {void}
|
|
88
88
|
*/
|
|
89
|
-
public setOrientation(orientationType:
|
|
89
|
+
public setOrientation(orientationType: OrientationTypes, size: number = TOOLBAR_SIZE): void {
|
|
90
90
|
this.orientation = orientationType;
|
|
91
91
|
this.size = size;
|
|
92
92
|
}
|
package/src/ui/widget.ui.ts
CHANGED
|
@@ -113,6 +113,30 @@ export class Widget implements IWidget {
|
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
+
this.body.addEventListener("wheel", (e) => {
|
|
117
|
+
this.subscribers.forEach((callback) => {
|
|
118
|
+
if (callback.event == "wheel") {
|
|
119
|
+
callback.then(e, this);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
this.body.addEventListener("mouseout", (e) => {
|
|
125
|
+
this.subscribers.forEach((callback) => {
|
|
126
|
+
if (callback.event == "mouseout") {
|
|
127
|
+
callback.then(e, this);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
this.body.addEventListener("mouseleave", (e) => {
|
|
133
|
+
this.subscribers.forEach((callback) => {
|
|
134
|
+
if (callback.event == "mouseleave") {
|
|
135
|
+
callback.then(e, this);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
116
140
|
this.init();
|
|
117
141
|
|
|
118
142
|
this.getMaxZIndex();
|
|
@@ -120,8 +144,18 @@ export class Widget implements IWidget {
|
|
|
120
144
|
window.w.set(this.id, this);
|
|
121
145
|
}
|
|
122
146
|
|
|
147
|
+
public run(eventId: WUIEvent): void {
|
|
148
|
+
this.subscribers.forEach((callback) => {
|
|
149
|
+
if (callback.event == eventId) {
|
|
150
|
+
callback.then(new Event(eventId), this);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
123
155
|
public subscribe(cb: WUICallback) {
|
|
124
|
-
const randomId =
|
|
156
|
+
const randomId =
|
|
157
|
+
Math.random().toString(36).substring(2, 15) +
|
|
158
|
+
Math.random().toString(36).substring(2, 15);
|
|
125
159
|
|
|
126
160
|
this.subscribers.set(`${randomId}.${cb.event}`, cb);
|
|
127
161
|
}
|