gtk3-node 1.0.0 → 1.2.0
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/CHANGELOG.md +2 -0
- package/CHECKLIST.md +30 -7
- package/binding.gyp +59 -0
- package/ejemplos/avanzados/README.md +2 -0
- package/ejemplos/avanzados/ejemplo_stringgrid_completo.js +95 -0
- package/ejemplos/avanzados/ejemplo_textview.js +65 -0
- package/ejemplos/intermedios/README.md +1 -0
- package/ejemplos/intermedios/ejemplo_entry.js +50 -0
- package/index.js +85 -0
- package/package.json +5 -1
- package/src/button.cpp +146 -0
- package/src/gtk3_node.cpp +162 -0
- package/widgets/box/README.md +42 -0
- package/widgets/box/box.cpp +77 -0
- package/widgets/box/box.h +10 -0
- package/widgets/entry/README.md +46 -0
- package/widgets/entry/entry.cpp +98 -0
- package/widgets/entry/entry.h +10 -0
- package/widgets/label/README.md +41 -0
- package/widgets/label/label.cpp +95 -0
- package/widgets/label/label.h +10 -0
- package/widgets/scroll/README.md +40 -0
- package/widgets/scroll/scroll.cpp +72 -0
- package/widgets/scroll/scroll.h +10 -0
- package/widgets/stringgrid/README.md +46 -0
- package/widgets/stringgrid/stringgrid.cpp +496 -0
- package/widgets/stringgrid/stringgrid.h +10 -0
- package/widgets/textview/README.md +48 -0
- package/widgets/textview/textview.cpp +209 -0
- package/widgets/textview/textview.h +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
- Widget Label para mostrar texto estático
|
|
11
11
|
- Widget Box para layouts horizontales y verticales
|
|
12
12
|
- Widget Scroll para contenedores con barras de desplazamiento
|
|
13
|
+
- Widget Entry para entrada de texto simple
|
|
14
|
+
- Widget StringGrid para tablas bidimensionales de datos
|
|
13
15
|
- Estructura modular para futuras expansiones
|
|
14
16
|
- Ejemplos organizados por niveles de complejidad
|
|
15
17
|
- Principio DRY aplicado en la arquitectura
|
package/CHECKLIST.md
CHANGED
|
@@ -42,13 +42,36 @@
|
|
|
42
42
|
- [x] Documentación completa
|
|
43
43
|
- [x] Ejemplos funcionales
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
### ✅ Entry
|
|
46
|
+
- [x] Creación de campos de texto simples
|
|
47
|
+
- [x] Soporte para entrada de texto
|
|
48
|
+
- [x] Lectura de texto ingresado
|
|
49
|
+
- [x] Escritura de texto programática
|
|
50
|
+
- [x] Documentación completa
|
|
51
|
+
- [x] Ejemplos funcionales
|
|
46
52
|
|
|
47
|
-
###
|
|
48
|
-
- [
|
|
53
|
+
### ✅ StringGrid
|
|
54
|
+
- [x] Creación de tablas bidimensionales
|
|
55
|
+
- [x] Soporte para filas y columnas
|
|
56
|
+
- [x] Establecimiento de encabezados
|
|
57
|
+
- [x] Agregar filas de datos
|
|
58
|
+
- [x] Modificación de celdas
|
|
59
|
+
- [x] Edición interactiva de celdas
|
|
60
|
+
- [x] Selección de filas
|
|
61
|
+
- [x] Callbacks de eventos
|
|
62
|
+
- [x] Documentación completa
|
|
63
|
+
- [x] Ejemplos funcionales
|
|
49
64
|
|
|
50
|
-
###
|
|
51
|
-
- [
|
|
65
|
+
### ✅ TextView
|
|
66
|
+
- [x] Área de texto multilinea para entradas más largas
|
|
67
|
+
- [x] Soporte para texto largo y desplazamiento
|
|
68
|
+
- [x] Lectura y escritura de texto
|
|
69
|
+
- [x] Añadir texto al contenido existente
|
|
70
|
+
- [x] Insertar texto en posiciones específicas
|
|
71
|
+
- [x] Documentación completa
|
|
72
|
+
- [x] Ejemplos funcionales
|
|
73
|
+
|
|
74
|
+
## Widgets Pendientes
|
|
52
75
|
|
|
53
76
|
### ❌ CheckButton
|
|
54
77
|
- [ ] Casilla de verificación
|
|
@@ -70,7 +93,7 @@
|
|
|
70
93
|
|
|
71
94
|
## Estado General
|
|
72
95
|
|
|
73
|
-
- **Total Widgets Implementados:**
|
|
74
|
-
- **Estado de la Extensión:** Funcional para casos básicos
|
|
96
|
+
- **Total Widgets Implementados:** 6/12
|
|
97
|
+
- **Estado de la Extensión:** Funcional para casos básicos e intermedios
|
|
75
98
|
- **Compatibilidad:** GTK3, Linux
|
|
76
99
|
- **Principio DRY:** Aplicado en toda la arquitectura
|
package/binding.gyp
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"targets": [
|
|
3
|
+
{
|
|
4
|
+
"target_name": "gtk3_node",
|
|
5
|
+
"sources": [
|
|
6
|
+
"src/gtk3_node.cpp",
|
|
7
|
+
"src/button.cpp",
|
|
8
|
+
"widgets/label/label.cpp",
|
|
9
|
+
"widgets/box/box.cpp",
|
|
10
|
+
"widgets/scroll/scroll.cpp",
|
|
11
|
+
"widgets/entry/entry.cpp",
|
|
12
|
+
"widgets/stringgrid/stringgrid.cpp",
|
|
13
|
+
"widgets/textview/textview.cpp"
|
|
14
|
+
],
|
|
15
|
+
"include_dirs": [
|
|
16
|
+
"<!@(node -p \"require('node-addon-api').include\")",
|
|
17
|
+
"/usr/include/gtk-3.0",
|
|
18
|
+
"/usr/include/glib-2.0",
|
|
19
|
+
"/usr/lib/x86_64-linux-gnu/glib-2.0/include",
|
|
20
|
+
"/usr/include/pango-1.0",
|
|
21
|
+
"/usr/include/harfbuzz",
|
|
22
|
+
"/usr/include/freetype2",
|
|
23
|
+
"/usr/include/libpng16",
|
|
24
|
+
"/usr/include/libmount",
|
|
25
|
+
"/usr/include/blkid",
|
|
26
|
+
"/usr/include/fribidi",
|
|
27
|
+
"/usr/include/cairo",
|
|
28
|
+
"/usr/include/pixman-1",
|
|
29
|
+
"/usr/include/gdk-pixbuf-2.0",
|
|
30
|
+
"/usr/include/x86_64-linux-gnu",
|
|
31
|
+
"/usr/include/gio-unix-2.0",
|
|
32
|
+
"/usr/include/atk-1.0",
|
|
33
|
+
"/usr/include/at-spi2-atk/2.0",
|
|
34
|
+
"/usr/include/at-spi-2.0",
|
|
35
|
+
"/usr/include/dbus-1.0",
|
|
36
|
+
"/usr/lib/x86_64-linux-gnu/dbus-1.0/include"
|
|
37
|
+
],
|
|
38
|
+
"libraries": [
|
|
39
|
+
"-lgtk-3",
|
|
40
|
+
"-lgobject-2.0",
|
|
41
|
+
"-lglib-2.0",
|
|
42
|
+
"-lgdk-3",
|
|
43
|
+
"-lpango-1.0",
|
|
44
|
+
"-lcairo",
|
|
45
|
+
"-lgdk_pixbuf-2.0",
|
|
46
|
+
"-latk-1.0"
|
|
47
|
+
],
|
|
48
|
+
"cflags": [
|
|
49
|
+
"-std=c++17"
|
|
50
|
+
],
|
|
51
|
+
"cflags_cc": [
|
|
52
|
+
"-std=c++17"
|
|
53
|
+
],
|
|
54
|
+
"defines": [
|
|
55
|
+
"NAPI_DISABLE_CPP_EXCEPTIONS"
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
@@ -6,6 +6,8 @@ Este directorio contiene ejemplos complejos que demuestran el uso combinado de m
|
|
|
6
6
|
|
|
7
7
|
- `ejemplo_completo.js` - Ejemplo con botón y 35 labels organizadas en layouts horizontales y verticales
|
|
8
8
|
- `ejemplo_scroll.js` - Ejemplo con Scroll, Labels y Buttons en la misma ventana
|
|
9
|
+
- `ejemplo_stringgrid_completo.js` - Ejemplo completo del StringGrid con todas sus capacidades
|
|
10
|
+
- `ejemplo_textview.js` - Ejemplo del widget TextView
|
|
9
11
|
|
|
10
12
|
## Objetivo
|
|
11
13
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// ejemplo_stringgrid_completo.js - Ejemplo completo del StringGrid con todas sus capacidades
|
|
2
|
+
|
|
3
|
+
const { StringGrid, Entry, Label, Button, Box, Scroll, Window, init, run } = require('../../index.js');
|
|
4
|
+
|
|
5
|
+
// Inicializar GTK
|
|
6
|
+
init();
|
|
7
|
+
|
|
8
|
+
// Crear una ventana
|
|
9
|
+
const ventana = new Window('StringGrid Completo', 900, 700);
|
|
10
|
+
|
|
11
|
+
// Crear un contenedor con scroll
|
|
12
|
+
const scroll = new Scroll();
|
|
13
|
+
|
|
14
|
+
// Crear un layout vertical
|
|
15
|
+
const layout = new Box('vertical');
|
|
16
|
+
|
|
17
|
+
// Crear un StringGrid con 15 filas y 5 columnas
|
|
18
|
+
const grid = new StringGrid(15, 5);
|
|
19
|
+
|
|
20
|
+
// Establecer encabezados
|
|
21
|
+
grid.setHeader(['Nombre', 'Edad', 'Ciudad', 'País', 'Activo']);
|
|
22
|
+
|
|
23
|
+
// Agregar algunas filas de ejemplo
|
|
24
|
+
grid.addRow(['Juan Pérez', '30', 'Madrid', 'España', 'Sí']);
|
|
25
|
+
grid.addRow(['Ana García', '25', 'Barcelona', 'España', 'No']);
|
|
26
|
+
grid.addRow(['Carlos López', '35', 'Buenos Aires', 'Argentina', 'Sí']);
|
|
27
|
+
grid.addRow(['María Rodríguez', '28', 'Ciudad de México', 'México', 'Sí']);
|
|
28
|
+
grid.addRow(['Pedro Fernández', '42', 'Bogotá', 'Colombia', 'No']);
|
|
29
|
+
|
|
30
|
+
// Crear controles para la interacción
|
|
31
|
+
const controlsLayout = new Box('horizontal');
|
|
32
|
+
|
|
33
|
+
const labelInfo = new Label('Información: ');
|
|
34
|
+
const entryInput = new Entry('Texto para celda');
|
|
35
|
+
const buttonUpdate = new Button('Actualizar Celda (0,0)');
|
|
36
|
+
const buttonGetSelected = new Button('Obtener Selección');
|
|
37
|
+
const labelSelection = new Label('Selección: Ninguna');
|
|
38
|
+
|
|
39
|
+
// Variables para almacenar la selección actual
|
|
40
|
+
let selectedRow = -1;
|
|
41
|
+
let selectedCol = -1;
|
|
42
|
+
|
|
43
|
+
// Registrar un callback para cuando se edita una celda
|
|
44
|
+
grid.registerCellEditCallback((info) => {
|
|
45
|
+
console.log(`Celda editada: fila=${info.row}, col=${info.col}, nuevo_valor="${info.newValue}"`);
|
|
46
|
+
labelInfo.text = `Celda (${info.row},${info.col}) actualizada a: "${info.newValue}"`;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Agregar un manejador de eventos al botón de actualizar
|
|
50
|
+
buttonUpdate.onClick(() => {
|
|
51
|
+
const texto = entryInput.text;
|
|
52
|
+
console.log(`Actualizando celda (0,0) con: ${texto}`);
|
|
53
|
+
grid.setCellValue(0, 0, texto);
|
|
54
|
+
labelInfo.text = `Celda (0,0) actualizada a: "${texto}"`;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Agregar un manejador de eventos al botón de obtener selección
|
|
58
|
+
buttonGetSelected.onClick(() => {
|
|
59
|
+
const selection = grid.getSelectedCell();
|
|
60
|
+
selectedRow = selection.row;
|
|
61
|
+
selectedCol = selection.col;
|
|
62
|
+
|
|
63
|
+
if (selection.row !== -1) {
|
|
64
|
+
const cellValue = grid.getCell(selection.row, 0); // Obtener valor de la primera columna
|
|
65
|
+
labelSelection.text = `Fila seleccionada: ${selection.row}, Valor: "${cellValue}"`;
|
|
66
|
+
console.log(`Fila seleccionada: ${selection.row}, Columna: ${selection.col}`);
|
|
67
|
+
} else {
|
|
68
|
+
labelSelection.text = 'Ninguna fila seleccionada';
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Agregar widgets al layout de controles
|
|
73
|
+
controlsLayout.add(labelInfo);
|
|
74
|
+
controlsLayout.add(entryInput);
|
|
75
|
+
controlsLayout.add(buttonUpdate);
|
|
76
|
+
controlsLayout.add(buttonGetSelected);
|
|
77
|
+
controlsLayout.add(labelSelection);
|
|
78
|
+
|
|
79
|
+
// Agregar widgets al layout principal
|
|
80
|
+
layout.add(grid);
|
|
81
|
+
layout.add(controlsLayout);
|
|
82
|
+
|
|
83
|
+
// Agregar el layout al contenedor con scroll
|
|
84
|
+
scroll.add(layout);
|
|
85
|
+
|
|
86
|
+
// Agregar el scroll a la ventana
|
|
87
|
+
ventana.add(scroll);
|
|
88
|
+
|
|
89
|
+
// Mostrar la ventana y todos sus contenidos
|
|
90
|
+
ventana.show();
|
|
91
|
+
|
|
92
|
+
console.log('Interfaz con StringGrid completa lista. Abriendo ventana...');
|
|
93
|
+
|
|
94
|
+
// Iniciar el loop de eventos GTK para mostrar la interfaz
|
|
95
|
+
run();
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// ejemplo_textview.js - Ejemplo del widget TextView
|
|
2
|
+
|
|
3
|
+
const { TextView, Button, Label, Box, Scroll, Window, init, run } = require('../../index.js');
|
|
4
|
+
|
|
5
|
+
// Inicializar GTK
|
|
6
|
+
init();
|
|
7
|
+
|
|
8
|
+
// Crear una ventana
|
|
9
|
+
const ventana = new Window('Ejemplo TextView', 600, 500);
|
|
10
|
+
|
|
11
|
+
// Crear un contenedor con scroll para el TextView
|
|
12
|
+
const scroll = new Scroll();
|
|
13
|
+
|
|
14
|
+
// Crear un TextView con texto inicial
|
|
15
|
+
const textView = new TextView('Hola,\neste es un ejemplo de TextView\ncon múltiples líneas.\n\nPuedes editar este texto directamente.');
|
|
16
|
+
|
|
17
|
+
// Crear controles para interactuar con el TextView
|
|
18
|
+
const controlsLayout = new Box('vertical');
|
|
19
|
+
|
|
20
|
+
const labelInfo = new Label('Usa los botones para interactuar con el TextView');
|
|
21
|
+
const buttonGetText = new Button('Obtener Texto');
|
|
22
|
+
const buttonSetText = new Button('Establecer Texto');
|
|
23
|
+
const buttonAppend = new Button('Añadir Texto');
|
|
24
|
+
|
|
25
|
+
// Agregar manejadores de eventos a los botones
|
|
26
|
+
buttonGetText.onClick(() => {
|
|
27
|
+
const text = textView.text;
|
|
28
|
+
console.log('Texto actual del TextView:', text);
|
|
29
|
+
labelInfo.text = `Caracteres: ${text.length}`;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
buttonSetText.onClick(() => {
|
|
33
|
+
textView.text = 'Texto completamente nuevo\nEscrito desde JavaScript\nCon múltiples líneas';
|
|
34
|
+
labelInfo.text = 'Texto actualizado';
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
buttonAppend.onClick(() => {
|
|
38
|
+
textView.appendText('\n\nTexto añadido al final');
|
|
39
|
+
labelInfo.text = 'Texto añadido al final';
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Agregar widgets al layout de controles
|
|
43
|
+
controlsLayout.add(labelInfo);
|
|
44
|
+
controlsLayout.add(buttonGetText);
|
|
45
|
+
controlsLayout.add(buttonSetText);
|
|
46
|
+
controlsLayout.add(buttonAppend);
|
|
47
|
+
|
|
48
|
+
// Agregar el TextView al contenedor con scroll
|
|
49
|
+
scroll.add(textView);
|
|
50
|
+
|
|
51
|
+
// Crear un layout principal
|
|
52
|
+
const mainLayout = new Box('vertical');
|
|
53
|
+
mainLayout.add(scroll);
|
|
54
|
+
mainLayout.add(controlsLayout);
|
|
55
|
+
|
|
56
|
+
// Agregar el layout principal a la ventana
|
|
57
|
+
ventana.add(mainLayout);
|
|
58
|
+
|
|
59
|
+
// Mostrar la ventana y todos sus contenidos
|
|
60
|
+
ventana.show();
|
|
61
|
+
|
|
62
|
+
console.log('Interfaz con TextView lista. Abriendo ventana...');
|
|
63
|
+
|
|
64
|
+
// Iniciar el loop de eventos GTK para mostrar la interfaz
|
|
65
|
+
run();
|
|
@@ -6,6 +6,7 @@ Este directorio contiene ejemplos que muestran el uso combinado de múltiples wi
|
|
|
6
6
|
|
|
7
7
|
- `ejemplo_label.js` - Ejemplo con widget Label y manipulación de texto
|
|
8
8
|
- `ejemplo_label_boton.js` - Ejemplo con Label y Button en la misma ventana
|
|
9
|
+
- `ejemplo_entry.js` - Ejemplo con Entry, Label y Button en la misma ventana
|
|
9
10
|
|
|
10
11
|
## Objetivo
|
|
11
12
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// ejemplo_entry.js - Ejemplo con Entry, Label y Button en la misma ventana
|
|
2
|
+
|
|
3
|
+
const { Button, Label, Entry, Box, Scroll, Window, init, run } = require('../../index.js');
|
|
4
|
+
|
|
5
|
+
// Inicializar GTK
|
|
6
|
+
init();
|
|
7
|
+
|
|
8
|
+
// Crear una ventana
|
|
9
|
+
const ventana = new Window('Ejemplo Entry, Label y Button', 500, 400);
|
|
10
|
+
|
|
11
|
+
// Crear un contenedor con scroll
|
|
12
|
+
const scroll = new Scroll();
|
|
13
|
+
|
|
14
|
+
// Crear un layout vertical
|
|
15
|
+
const layout = new Box('vertical');
|
|
16
|
+
|
|
17
|
+
// Crear un label para mostrar el texto del entry
|
|
18
|
+
const label = new Label('Ingresa texto en el campo de abajo y haz clic en el botón');
|
|
19
|
+
|
|
20
|
+
// Crear un entry
|
|
21
|
+
const entry = new Entry('Texto inicial...');
|
|
22
|
+
|
|
23
|
+
// Crear un botón
|
|
24
|
+
const boton = new Button('Obtener texto del Entry');
|
|
25
|
+
|
|
26
|
+
// Agregar un manejador de eventos al botón
|
|
27
|
+
boton.onClick(() => {
|
|
28
|
+
const textoEntrada = entry.text;
|
|
29
|
+
console.log('Texto del entry:', textoEntrada);
|
|
30
|
+
label.text = `Texto ingresado: "${textoEntrada}"`;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Agregar widgets al layout
|
|
34
|
+
layout.add(label);
|
|
35
|
+
layout.add(entry);
|
|
36
|
+
layout.add(boton);
|
|
37
|
+
|
|
38
|
+
// Agregar el layout al contenedor con scroll
|
|
39
|
+
scroll.add(layout);
|
|
40
|
+
|
|
41
|
+
// Agregar el scroll a la ventana
|
|
42
|
+
ventana.add(scroll);
|
|
43
|
+
|
|
44
|
+
// Mostrar la ventana y todos sus contenidos
|
|
45
|
+
ventana.show();
|
|
46
|
+
|
|
47
|
+
console.log('Interfaz con Entry, Label y Button lista. Abriendo ventana...');
|
|
48
|
+
|
|
49
|
+
// Iniciar el loop de eventos GTK para mostrar la interfaz
|
|
50
|
+
run();
|
package/index.js
CHANGED
|
@@ -66,6 +66,88 @@ class Scroll {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
class Entry {
|
|
70
|
+
constructor(text = "") {
|
|
71
|
+
this.widget = gtk3_native.createEntry(text);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
set text(content) {
|
|
75
|
+
gtk3_native.setEntryText(this.widget, content);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
get text() {
|
|
79
|
+
return gtk3_native.getEntryText(this.widget);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
setText(content) {
|
|
83
|
+
this.text = content;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getText() {
|
|
87
|
+
return this.text;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
class StringGrid {
|
|
92
|
+
constructor(rows = 10, cols = 5) {
|
|
93
|
+
this.widget = gtk3_native.createStringGrid(rows, cols);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
setCellValue(row, col, value) {
|
|
97
|
+
return gtk3_native.setGridCellValue(this.widget, row, col, value);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
getCell(row, col) {
|
|
101
|
+
return gtk3_native.getGridCell(this.widget, row, col);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
setHeader(headers) {
|
|
105
|
+
return gtk3_native.setGridHeader(this.widget, headers);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
addRow(data) {
|
|
109
|
+
return gtk3_native.addGridRow(this.widget, data);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
getSelectedCell() {
|
|
113
|
+
return gtk3_native.getSelectedCell(this.widget);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
registerCellEditCallback(callback) {
|
|
117
|
+
return gtk3_native.registerCellEditCallback(this.widget, callback);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
class TextView {
|
|
122
|
+
constructor(text = "") {
|
|
123
|
+
this.widget = gtk3_native.createTextView(text);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
set text(content) {
|
|
127
|
+
gtk3_native.setTextViewText(this.widget, content);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
get text() {
|
|
131
|
+
return gtk3_native.getTextViewText(this.widget);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
setText(content) {
|
|
135
|
+
this.text = content;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
getText() {
|
|
139
|
+
return this.text;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
appendText(content) {
|
|
143
|
+
return gtk3_native.appendTextViewText(this.widget, content);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
insertText(position, content) {
|
|
147
|
+
return gtk3_native.insertTextViewText(this.widget, position, content);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
69
151
|
class Window {
|
|
70
152
|
constructor(title = "Ventana", width = 400, height = 300) {
|
|
71
153
|
this.widget = gtk3_native.createWindow(title, width, height);
|
|
@@ -99,6 +181,9 @@ module.exports = {
|
|
|
99
181
|
Label,
|
|
100
182
|
Box,
|
|
101
183
|
Scroll,
|
|
184
|
+
Entry,
|
|
185
|
+
StringGrid,
|
|
186
|
+
TextView,
|
|
102
187
|
Window,
|
|
103
188
|
// Mantener compatibilidad hacia atrás
|
|
104
189
|
createWindow: gtk3_native.createWindow,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gtk3-node",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Native Node.js extension for creating GTK3 widgets",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -48,6 +48,10 @@
|
|
|
48
48
|
],
|
|
49
49
|
"author": "Usuario",
|
|
50
50
|
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "https://gitlab.com/bytedogssyndicate1/nodetk3.git"
|
|
54
|
+
},
|
|
51
55
|
"dependencies": {
|
|
52
56
|
"node-addon-api": "^7.0.0"
|
|
53
57
|
},
|
package/src/button.cpp
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#include <napi.h>
|
|
2
|
+
#include <gtk/gtk.h>
|
|
3
|
+
|
|
4
|
+
// Estructura para almacenar datos del botón
|
|
5
|
+
struct ButtonData {
|
|
6
|
+
GtkWidget* button;
|
|
7
|
+
Napi::FunctionReference callback;
|
|
8
|
+
Napi::Env env;
|
|
9
|
+
|
|
10
|
+
ButtonData(Napi::Env e) : button(nullptr), env(e) {}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Callback para el evento de clic en GTK
|
|
14
|
+
static void button_click_callback(GtkWidget *widget, gpointer data) {
|
|
15
|
+
ButtonData* btn_data = static_cast<ButtonData*>(data);
|
|
16
|
+
|
|
17
|
+
if (!btn_data->callback.IsEmpty()) {
|
|
18
|
+
Napi::HandleScope scope(btn_data->env);
|
|
19
|
+
btn_data->callback.Call({});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Constructor de botón
|
|
24
|
+
Napi::Value CreateButton(const Napi::CallbackInfo& info) {
|
|
25
|
+
Napi::Env env = info.Env();
|
|
26
|
+
|
|
27
|
+
std::string label = "Button";
|
|
28
|
+
if (info.Length() > 0 && info[0].IsString()) {
|
|
29
|
+
label = info[0].As<Napi::String>().Utf8Value();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
GtkWidget* button = gtk_button_new_with_label(label.c_str());
|
|
33
|
+
|
|
34
|
+
// Crear estructura de datos para el botón
|
|
35
|
+
ButtonData* btn_data = new ButtonData(env);
|
|
36
|
+
btn_data->button = button;
|
|
37
|
+
|
|
38
|
+
// Guardar la estructura en los datos del widget
|
|
39
|
+
g_object_set_data_full(G_OBJECT(button), "button_data", btn_data,
|
|
40
|
+
GDestroyNotify([](gpointer data) {
|
|
41
|
+
ButtonData* btn_data = static_cast<ButtonData*>(data);
|
|
42
|
+
if (!btn_data->callback.IsEmpty()) {
|
|
43
|
+
btn_data->callback.Reset();
|
|
44
|
+
}
|
|
45
|
+
delete btn_data;
|
|
46
|
+
}));
|
|
47
|
+
|
|
48
|
+
// Convertir el widget a External para pasarlo a JavaScript
|
|
49
|
+
Napi::Object obj = Napi::Object::New(env);
|
|
50
|
+
obj.Set("widget", Napi::External<GtkWidget>::New(env, button));
|
|
51
|
+
|
|
52
|
+
return obj;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Función para conectar el callback de clic
|
|
56
|
+
Napi::Value ConnectClick(const Napi::CallbackInfo& info) {
|
|
57
|
+
Napi::Env env = info.Env();
|
|
58
|
+
|
|
59
|
+
if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsFunction()) {
|
|
60
|
+
Napi::TypeError::New(env, "Se requiere un objeto widget y una función callback").ThrowAsJavaScriptException();
|
|
61
|
+
return Napi::Boolean::New(env, false);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Napi::Object widgetObj = info[0].As<Napi::Object>();
|
|
65
|
+
Napi::Function callback = info[1].As<Napi::Function>();
|
|
66
|
+
|
|
67
|
+
if (!widgetObj.HasOwnProperty("widget")) {
|
|
68
|
+
Napi::TypeError::New(env, "El objeto no contiene un widget válido").ThrowAsJavaScriptException();
|
|
69
|
+
return Napi::Boolean::New(env, false);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Napi::External<GtkWidget> widgetExt = widgetObj.Get("widget").As<Napi::External<GtkWidget>>();
|
|
73
|
+
GtkWidget* button = widgetExt.Data();
|
|
74
|
+
|
|
75
|
+
// Obtener la estructura de datos del botón
|
|
76
|
+
ButtonData* btn_data = static_cast<ButtonData*>(g_object_get_data(G_OBJECT(button), "button_data"));
|
|
77
|
+
if (!btn_data) {
|
|
78
|
+
Napi::TypeError::New(env, "Datos del botón no encontrados").ThrowAsJavaScriptException();
|
|
79
|
+
return Napi::Boolean::New(env, false);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Almacenar el nuevo callback
|
|
83
|
+
btn_data->callback.Reset(callback, 1);
|
|
84
|
+
|
|
85
|
+
// Conectar el callback de GTK
|
|
86
|
+
g_signal_connect(button, "clicked", G_CALLBACK(button_click_callback), btn_data);
|
|
87
|
+
|
|
88
|
+
return Napi::Boolean::New(env, true);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Función para cambiar el texto del botón
|
|
92
|
+
Napi::Value SetButtonText(const Napi::CallbackInfo& info) {
|
|
93
|
+
Napi::Env env = info.Env();
|
|
94
|
+
|
|
95
|
+
if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsString()) {
|
|
96
|
+
Napi::TypeError::New(env, "Se requiere un objeto widget y un texto").ThrowAsJavaScriptException();
|
|
97
|
+
return Napi::Boolean::New(env, false);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
Napi::Object widgetObj = info[0].As<Napi::Object>();
|
|
101
|
+
std::string newText = info[1].As<Napi::String>().Utf8Value();
|
|
102
|
+
|
|
103
|
+
if (!widgetObj.HasOwnProperty("widget")) {
|
|
104
|
+
Napi::TypeError::New(env, "El objeto no contiene un widget válido").ThrowAsJavaScriptException();
|
|
105
|
+
return Napi::Boolean::New(env, false);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
Napi::External<GtkWidget> widgetExt = widgetObj.Get("widget").As<Napi::External<GtkWidget>>();
|
|
109
|
+
GtkWidget* button = widgetExt.Data();
|
|
110
|
+
|
|
111
|
+
gtk_button_set_label(GTK_BUTTON(button), newText.c_str());
|
|
112
|
+
|
|
113
|
+
return Napi::Boolean::New(env, true);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Función para obtener el texto del botón
|
|
117
|
+
Napi::Value GetButtonText(const Napi::CallbackInfo& info) {
|
|
118
|
+
Napi::Env env = info.Env();
|
|
119
|
+
|
|
120
|
+
if (info.Length() < 1 || !info[0].IsObject()) {
|
|
121
|
+
Napi::TypeError::New(env, "Se requiere un objeto widget").ThrowAsJavaScriptException();
|
|
122
|
+
return Napi::String::New(env, "");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Napi::Object widgetObj = info[0].As<Napi::Object>();
|
|
126
|
+
|
|
127
|
+
if (!widgetObj.HasOwnProperty("widget")) {
|
|
128
|
+
Napi::TypeError::New(env, "El objeto no contiene un widget válido").ThrowAsJavaScriptException();
|
|
129
|
+
return Napi::String::New(env, "");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
Napi::External<GtkWidget> widgetExt = widgetObj.Get("widget").As<Napi::External<GtkWidget>>();
|
|
133
|
+
GtkWidget* button = widgetExt.Data();
|
|
134
|
+
|
|
135
|
+
const gchar* text = gtk_button_get_label(GTK_BUTTON(button));
|
|
136
|
+
return Napi::String::New(env, text ? text : "");
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
Napi::Object InitButton(Napi::Env env, Napi::Object exports) {
|
|
140
|
+
exports.Set("createButton", Napi::Function::New(env, CreateButton));
|
|
141
|
+
exports.Set("connectClick", Napi::Function::New(env, ConnectClick));
|
|
142
|
+
exports.Set("setButtonText", Napi::Function::New(env, SetButtonText));
|
|
143
|
+
exports.Set("getButtonText", Napi::Function::New(env, GetButtonText));
|
|
144
|
+
|
|
145
|
+
return exports;
|
|
146
|
+
}
|