add splash screen and making library manager

This commit is contained in:
dharm pimsen 2024-07-14 21:24:30 +07:00
parent c2d0f4b970
commit f6f9e02542
24 changed files with 918 additions and 549 deletions

BIN
assets/noimagefallback.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -11,5 +11,5 @@ luaGenerator.forBlock['ide_addcode'] = function(block, generator) {
// Remove all occurrences of the matched characters
const cleanedStr = codefromuser.replace(/[']/g, '');
return cleanedStr;
return cleanedStr+"\n";
};

View File

@ -9,6 +9,7 @@
"peripherals": false,
"library": false,
"turtle": false,
"pocket": false,
"require_network": false,
"dependencies": {}
}

View File

@ -0,0 +1,87 @@
{
"math_operation": {
"message0": "args %1 %2 %3",
"args0": [
{
"type": "field_dropdown",
"name": "OPERATOR",
"options": [
["+", "ADD"],
["-", "SUBTRACT"],
["*", "MULTIPLY"],
["/", "DIVIDE"]
]
},
{
"type": "input_value",
"name": "NUM1",
"check": "Number"
},
{
"type": "input_value",
"name": "NUM2",
"check": "Number"
}
],
"inputsInline": true,
"output": "Number",
"colour": 230,
"tooltip": "Perform a mathematical operation",
"helpUrl": ""
},
"text_print": {
"message0": "print %1",
"args0": [
{
"type": "input_value",
"name": "TEXT"
}
],
"previousStatement": null,
"nextStatement": null,
"colour": 160,
"tooltip": "Print text",
"helpUrl": ""
},
"controls_if": {
"message0": "if %1 then",
"args0": [
{
"type": "input_value",
"name": "IF0",
"check": "Boolean"
}
],
"message1": "do %1",
"args1": [
{
"type": "input_statement",
"name": "DO0"
}
],
"previousStatement": null,
"nextStatement": null,
"colour": 210,
"tooltip": "If condition",
"helpUrl": ""
},
"variables_set": {
"message0": "set %1 to %2",
"args0": [
{
"type": "field_variable",
"name": "VAR",
"variable": "item"
},
{
"type": "input_value",
"name": "VALUE"
}
],
"previousStatement": null,
"nextStatement": null,
"colour": 330,
"tooltip": "Set variable",
"helpUrl": ""
}
}

View File

@ -0,0 +1,58 @@
const { luaGenerator } = require('blockly/lua');
// Check if luaGenerator.forBlock is defined and initialize if necessary
if (!luaGenerator.forBlock) {
luaGenerator.forBlock = {};
}
// Math operation block
luaGenerator.forBlock['math_operation'] = function(block, generator) {
var operator = block.getFieldValue('OPERATOR');
var num1 = generator.valueToCode(block, 'NUM1', generator.ORDER_ATOMIC);
var num2 = generator.valueToCode(block, 'NUM2', generator.ORDER_ATOMIC);
var operatorSymbol = '';
switch (operator) {
case 'ADD':
operatorSymbol = '+';
break;
case 'SUBTRACT':
operatorSymbol = '-';
break;
case 'MULTIPLY':
operatorSymbol = '*';
break;
case 'DIVIDE':
operatorSymbol = '/';
break;
default:
operatorSymbol = '+';
break;
}
var code = `${num1} ${operatorSymbol} ${num2}`;
return [code, generator.ORDER_ATOMIC];
};
// Print text block
luaGenerator.forBlock['text_print'] = function(block, generator) {
var text = generator.valueToCode(block, 'TEXT', generator.ORDER_NONE) || '\'\'';
var code = `print(${text})\n`;
return code;
};
// If condition block
luaGenerator.forBlock['controls_if'] = function(block, generator) {
var condition = generator.valueToCode(block, 'IF0', generator.ORDER_NONE) || 'false';
var branch = generator.statementToCode(block, 'DO0');
var code = `if ${condition} then\n${branch}\nend\n`;
return code;
};
// Set variable block
luaGenerator.forBlock['variables_set'] = function(block, generator) {
var variable = generator.nameDB_.getName(block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
var value = generator.valueToCode(block, 'VALUE', generator.ORDER_NONE) || '0';
var code = `${variable} = ${value}\n`;
return code;
};

View File

@ -1,14 +1,15 @@
{
"name": "Test Peripheral",
"name": "Template",
"author": "DPSoftware Foundation",
"description": "Test Peripheral",
"description": "Template for creating custom blocks in ccIDE",
"version": "1.0.0",
"category": "Blockly Extensions",
"keyword": "test",
"category": "",
"keyword": "template, custom block, ccIDE",
"license": "GPL-3.0-or-later",
"peripherals": false,
"library": false,
"turtle": false,
"pocket": false,
"require_network": false,
"dependencies": {}
}
}

View File

@ -0,0 +1,44 @@
<xml id="toolbox" style="display: none;">
<category name="Template" colour="270">
<!-- Math operation block -->
<block type="math_operation">
<value name="NUM1">
<shadow type="math_number">
<field name="NUM">10</field> <!-- Default value -->
</shadow>
</value>
<value name="NUM2">
<shadow type="math_number">
<field name="NUM">5</field> <!-- Default value -->
</shadow>
</value>
</block>
<!-- Print text block -->
<block type="text_print">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">Hello, world!</field> <!-- Default value -->
</shadow>
</value>
</block>
<!-- If condition block -->
<block type="controls_if">
<value name="IF0">
<shadow type="logic_boolean">
<field name="BOOL">TRUE</field> <!-- Default value -->
</shadow>
</value>
</block>
<!-- Set variable block -->
<block type="variables_set">
<value name="VALUE">
<shadow type="math_number">
<field name="NUM">0</field> <!-- Default value -->
</shadow>
</value>
</block>
</category>
</xml>

View File

@ -1,32 +0,0 @@
{
"custom_math_operation": {
"message0": "%1 %2 %3",
"args0": [
{
"type": "field_dropdown",
"name": "OPERATOR",
"options": [
["+", "ADD"],
["-", "SUBTRACT"],
["*", "MULTIPLY"],
["/", "DIVIDE"]
]
},
{
"type": "input_value",
"name": "NUM1",
"check": "Number"
},
{
"type": "input_value",
"name": "NUM2",
"check": "Number"
}
],
"inputsInline": true,
"output": "Number",
"colour": 230,
"tooltip": "Perform a mathematical operation",
"helpUrl": ""
}
}

View File

@ -1,35 +0,0 @@
const { luaGenerator } = require('blockly/lua');
// Check if luaGenerator.forBlock is defined and initialize if necessary-
if (!luaGenerator.forBlock) {
luaGenerator.forBlock = {};
}
// Define your custom block handler
luaGenerator.forBlock['custom_math_operation'] = function(block, generator) {
var operator = block.getFieldValue('OPERATOR');
var num1 = generator.valueToCode(block, 'NUM1', generator.ORDER_ATOMIC);
var num2 = generator.valueToCode(block, 'NUM2', generator.ORDER_ATOMIC);
var operatorSymbol = '';
switch (operator) {
case 'ADD':
operatorSymbol = '+';
break;
case 'SUBTRACT':
operatorSymbol = '-';
break;
case 'MULTIPLY':
operatorSymbol = '*';
break;
case 'DIVIDE':
operatorSymbol = '/';
break;
default:
operatorSymbol = '+';
break;
}
var code = `${num1} ${operatorSymbol} ${num2}`;
return [code, generator.ORDER_ATOMIC];
};

View File

@ -1,17 +0,0 @@
<xml id="toolbox" style="display: none;">
<category name="Custom Blocks" colour="270">
<!-- Define your custom blocks here -->
<block type="custom_math_operation">
<value name="NUM1">
<shadow type="math_number">
<field name="NUM">10</field> <!-- Default value -->
</shadow>
</value>
<value name="NUM2">
<shadow type="math_number">
<field name="NUM">5</field> <!-- Default value -->
</shadow>
</value>
</block>
</category>
</xml>

Binary file not shown.

View File

@ -4,32 +4,61 @@ const prompt = require('electron-prompt');
const path = require('path');
const ipc = ipcMain
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
let currentprojectpath = null;
let currentprojectname = null;
let currentprojectopen = false
let appexiting = false
let currentprojectopen = false;
let appexiting = false;
let appreloading = false;
let currentworkspacechange = false;
let isopennewproject = false;
app.whenReady().then(() => {
currentprojectpath = null;
currentprojectname = null;
currentprojectopen = false;
appexiting = false;
reloadall(false);
const win = new BrowserWindow({
width: 1280,
height: 720,
icon: path.join(__dirname, '..', 'assets', 'ccIDEIcon.ico'),
icon: path.join(__dirname, 'assets', 'ccIDEIcon.ico'),
webPreferences: {
devTools: true,
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false,
}
},
show: false,
center: true,
})
win.loadFile('index.html')
//win.openDevTools();
win.maximize()
var splash = new BrowserWindow({
width: 600,
height: 300,
icon: path.join(__dirname, 'assets', 'ccIDEIcon.ico'),
transparent: true,
frame: false,
center: true
});
win.loadFile('src/index.html');
splash.loadFile('src/splash.html');
win.setTitle(`ccIDE`)
ipc.once('ready', () => {
console.log("ready")
if (splash) {
splash.close();
}
win.show();
win.maximize();
});
ipc.on('erroronstart', (event, errormessage) => {
dialog.showErrorBox("Error on startup", errormessage);
//win.openDevTools();
});
//app.on('activate', () => {
// if (BrowserWindow.getAllWindows().length === 0) {
@ -37,6 +66,21 @@ app.whenReady().then(() => {
// }
//})
function reloadall(isloaded=true) {
currentprojectpath = null;
currentprojectname = null;
currentprojectopen = false;
currentworkspacechange = false;
appexiting = false;
appreloading = false;
isopennewproject = false;
if (isloaded) {
win.setTitle(`ccIDE`)
win.reload();
}
}
// Define a custom menu template
const menuTemplate = [
{
@ -46,43 +90,106 @@ app.whenReady().then(() => {
label: 'New',
accelerator: 'CmdOrCtrl+N',
click: () => {
win.reload()
if (currentworkspacechange) {
const result = dialog.showMessageBoxSync({
type: 'question',
buttons: ['Save', 'Don\'t Save', 'Cancel'],
defaultId: 2,
title: 'Save Changes',
message: "Your project is not saved",
});
if (result === 1) {
// Don't save
reloadall();
} else if (result === 0) {
// Save
appreloading = true;
win.webContents.send('save-workspace-request');
}
} else {
reloadall();
}
}
},
{
label: 'Open',
accelerator: 'CmdOrCtrl+O',
click: () => {
dialog.showOpenDialog(win, {
title: 'Open Project',
defaultPath: app.getPath('documents'),
filters: [
{ name: 'ComputerCraft Project', extensions: ['ccp'] }
],
properties: ['openFile']
}).then(result => {
if (!result.canceled) {
const filePath = result.filePaths[0];
fs.readFile(filePath, 'utf8', (err, json) => {
if (err) {
console.error('Error loading workspace:', err);
return;
if (currentworkspacechange) {
const result = dialog.showMessageBoxSync({
type: 'question',
buttons: ['Save', 'Don\'t Save', 'Cancel'],
defaultId: 2,
title: 'Save Changes',
message: "Your project is not saved",
});
if (result === 1) {
// Don't save
dialog.showOpenDialog(win, {
title: 'Open Project',
defaultPath: app.getPath('documents'),
filters: [
{ name: 'ComputerCraft Project', extensions: ['ccp'] }
],
properties: ['openFile']
}).then(result => {
if (!result.canceled) {
const filePath = result.filePaths[0];
fs.readFile(filePath, 'utf8', (err, json) => {
if (err) {
console.error('Error loading workspace:', err);
return;
}
win.webContents.send('load-workspace', json);
currentprojectpath = result.filePaths[0]
currentprojectname = path.basename(result.filePaths[0]);
currentprojectopen = true;
win.setTitle(`${currentprojectname} | ccIDE`)
});
}
win.webContents.send('load-workspace', json);
currentprojectpath = result.filePaths[0]
currentprojectname = path.basename(result.filePaths[0]);
currentprojectopen = true;
win.setTitle(`${currentprojectname} | ccIDE`)
}).catch(err => {
console.error('Error showing open dialog:', err);
});
} else if (result === 0) {
// Save
isopennewproject = true;
win.webContents.send('save-workspace-request');
}
}).catch(err => {
console.error('Error showing open dialog:', err);
});
} else {
dialog.showOpenDialog(win, {
title: 'Open Project',
defaultPath: app.getPath('documents'),
filters: [
{ name: 'ComputerCraft Project', extensions: ['ccp'] }
],
properties: ['openFile']
}).then(result => {
if (!result.canceled) {
const filePath = result.filePaths[0];
fs.readFile(filePath, 'utf8', (err, json) => {
if (err) {
console.error('Error loading workspace:', err);
return;
}
win.webContents.send('load-workspace', json);
currentprojectpath = result.filePaths[0]
currentprojectname = path.basename(result.filePaths[0]);
currentprojectopen = true;
win.setTitle(`${currentprojectname} | ccIDE`)
});
}
}).catch(err => {
console.error('Error showing open dialog:', err);
});
}
}
},
{
@ -133,7 +240,7 @@ app.whenReady().then(() => {
{
label: 'About',
click: () => {
console.log('About clicked');
win.webContents.send("open-about")
}
}
]
@ -194,6 +301,9 @@ app.whenReady().then(() => {
win.webContents.send('workspace-saved', true);
win.setTitle(`${currentprojectname} | ccIDE`)
if (currentworkspacechange) {
currentworkspacechange = false;
}
}
});
} else {
@ -217,9 +327,47 @@ app.whenReady().then(() => {
win.setTitle(`${currentprojectname} | ccIDE`)
if (currentworkspacechange) {
currentworkspacechange = false;
}
if (appexiting) {
app.quit();
}
if (appreloading) {
reloadall();
}
if (isopennewproject) {
dialog.showOpenDialog(win, {
title: 'Open Project',
defaultPath: app.getPath('documents'),
filters: [
{ name: 'ComputerCraft Project', extensions: ['ccp'] }
],
properties: ['openFile']
}).then(result => {
if (!result.canceled) {
const filePath = result.filePaths[0];
fs.readFile(filePath, 'utf8', (err, json) => {
if (err) {
console.error('Error loading workspace:', err);
return;
}
win.webContents.send('load-workspace', json);
currentprojectpath = result.filePaths[0]
currentprojectname = path.basename(result.filePaths[0]);
currentprojectopen = true;
win.setTitle(`${currentprojectname} | ccIDE`)
});
}
}).catch(err => {
console.error('Error showing open dialog:', err);
});
}
}
});
}
@ -227,7 +375,11 @@ app.whenReady().then(() => {
ipc.on('workspace-notsave', (event) => {
win.setTitle(`${currentprojectname}* | ccIDE`)
})
currentworkspacechange = true;
})
ipc.on('workspace-unsave', (event) => {
currentworkspacechange = true;
})
})
@ -257,4 +409,10 @@ app.on("close", function(e) {
// No unsaved changes, continue closing
win = null;
}
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});

168
package-lock.json generated
View File

@ -9,39 +9,23 @@
"version": "1.0.2",
"license": "GPL-3.0-or-later",
"dependencies": {
"@blockly/field-multilineinput": "^5.0.5",
"@blockly/theme-dark": "^7.0.3",
"@electron-fonts/noto-sans": "^1.2.0",
"@electron/remote": "^2.1.2",
"blockly": "^11.1.1",
"bootstrap": "^5.3.3",
"electron-prompt": "^1.7.0",
"mergexml": "^1.2.4",
"xmldom": "^0.6.0"
},
"devDependencies": {
"electron": "^31.1.0"
}
},
"node_modules/@blockly/field-multilineinput": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/@blockly/field-multilineinput/-/field-multilineinput-5.0.5.tgz",
"integrity": "sha512-fCh+fkEeNCUwPyO6O45rH68e27RjMFWAvfUu/fYybGSIvt92uZfhZqq0veLMqAhwfYR7qQ7HIhUqvHQzAe4t6g==",
"engines": {
"node": ">=8.0.0"
},
"peerDependencies": {
"blockly": "^11.0.0"
}
},
"node_modules/@blockly/theme-dark": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-7.0.3.tgz",
"integrity": "sha512-lRV9V5vjijbJAlUdZqtEhUt81OjHjZK8vagxir1cUqTrZ/+MNS2m7wkhIVPba4RWInJ1LY/nHEoQn6demZqRRQ==",
"engines": {
"node": ">=8.17.0"
},
"peerDependencies": {
"blockly": "^11.0.0"
"node_modules/@electron-fonts/noto-sans": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@electron-fonts/noto-sans/-/noto-sans-1.2.0.tgz",
"integrity": "sha512-czys6R1EUpuc7sbK5h5SbVRE4HScbrnx4dlOrli7AyCWomSOYnAW+5nJevibZnTseFFe8MCdORaZoCe+LXe/1Q==",
"dependencies": {
"electron-css-injector": "1.3.0"
}
},
"node_modules/@electron/get": {
@ -153,14 +137,6 @@
"@types/node": "*"
}
},
"node_modules/@xmldom/xmldom": {
"version": "0.7.13",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz",
"integrity": "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/agent-base": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
@ -172,11 +148,6 @@
"node": ">= 14"
}
},
"node_modules/asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@ -397,15 +368,6 @@
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"optional": true
},
"node_modules/dezalgo": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
"dependencies": {
"asap": "^2.0.0",
"wrappy": "1"
}
},
"node_modules/electron": {
"version": "31.1.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-31.1.0.tgz",
@ -423,6 +385,11 @@
"node": ">= 12.20.55"
}
},
"node_modules/electron-css-injector": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/electron-css-injector/-/electron-css-injector-1.3.0.tgz",
"integrity": "sha512-xRpwgP2fYSkB21vtL6jC77p4Gn/bc6PH2M6kOe5tOJkUsznqk3kpDe/UHpuvehHH+MMn8Mf+g24PXEADWhSvIA=="
},
"node_modules/electron-prompt": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/electron-prompt/-/electron-prompt-1.7.0.tgz",
@ -534,19 +501,6 @@
"node": ">= 6"
}
},
"node_modules/formidable": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz",
"integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==",
"dependencies": {
"dezalgo": "^1.0.4",
"hexoid": "^1.0.0",
"once": "^1.4.0"
},
"funding": {
"url": "https://ko-fi.com/tunnckoCore/commissions"
}
},
"node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@ -736,14 +690,6 @@
"node": ">= 0.4"
}
},
"node_modules/hexoid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
"integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==",
"engines": {
"node": ">=8"
}
},
"node_modules/html-encoding-sniffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
@ -898,16 +844,6 @@
"node": ">=10"
}
},
"node_modules/mergexml": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/mergexml/-/mergexml-1.2.4.tgz",
"integrity": "sha512-yiOlDqcVCz7AG1eSboonc18FTlfqDEKYfGoAV3Lul98u6YRV/s0kjtf4bjk47t0hLTFJR0BSYMd6BpmX3xDjNQ==",
"dependencies": {
"@xmldom/xmldom": "^0.7.0",
"formidable": "^3.5.1",
"xpath": "0.0.27"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@ -1316,14 +1252,6 @@
"node": ">=10.0.0"
}
},
"node_modules/xpath": {
"version": "0.0.27",
"resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz",
"integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==",
"engines": {
"node": ">=0.6.0"
}
},
"node_modules/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
@ -1335,17 +1263,13 @@
}
},
"dependencies": {
"@blockly/field-multilineinput": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/@blockly/field-multilineinput/-/field-multilineinput-5.0.5.tgz",
"integrity": "sha512-fCh+fkEeNCUwPyO6O45rH68e27RjMFWAvfUu/fYybGSIvt92uZfhZqq0veLMqAhwfYR7qQ7HIhUqvHQzAe4t6g==",
"requires": {}
},
"@blockly/theme-dark": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-7.0.3.tgz",
"integrity": "sha512-lRV9V5vjijbJAlUdZqtEhUt81OjHjZK8vagxir1cUqTrZ/+MNS2m7wkhIVPba4RWInJ1LY/nHEoQn6demZqRRQ==",
"requires": {}
"@electron-fonts/noto-sans": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@electron-fonts/noto-sans/-/noto-sans-1.2.0.tgz",
"integrity": "sha512-czys6R1EUpuc7sbK5h5SbVRE4HScbrnx4dlOrli7AyCWomSOYnAW+5nJevibZnTseFFe8MCdORaZoCe+LXe/1Q==",
"requires": {
"electron-css-injector": "1.3.0"
}
},
"@electron/get": {
"version": "2.0.3",
@ -1436,11 +1360,6 @@
"@types/node": "*"
}
},
"@xmldom/xmldom": {
"version": "0.7.13",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz",
"integrity": "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g=="
},
"agent-base": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
@ -1449,11 +1368,6 @@
"debug": "^4.3.4"
}
},
"asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@ -1602,15 +1516,6 @@
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"optional": true
},
"dezalgo": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
"requires": {
"asap": "^2.0.0",
"wrappy": "1"
}
},
"electron": {
"version": "31.1.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-31.1.0.tgz",
@ -1621,6 +1526,11 @@
"extract-zip": "^2.0.1"
}
},
"electron-css-injector": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/electron-css-injector/-/electron-css-injector-1.3.0.tgz",
"integrity": "sha512-xRpwgP2fYSkB21vtL6jC77p4Gn/bc6PH2M6kOe5tOJkUsznqk3kpDe/UHpuvehHH+MMn8Mf+g24PXEADWhSvIA=="
},
"electron-prompt": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/electron-prompt/-/electron-prompt-1.7.0.tgz",
@ -1700,16 +1610,6 @@
"mime-types": "^2.1.12"
}
},
"formidable": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz",
"integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==",
"requires": {
"dezalgo": "^1.0.4",
"hexoid": "^1.0.0",
"once": "^1.4.0"
}
},
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@ -1841,11 +1741,6 @@
"function-bind": "^1.1.2"
}
},
"hexoid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
"integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g=="
},
"html-encoding-sniffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
@ -1968,16 +1863,6 @@
"escape-string-regexp": "^4.0.0"
}
},
"mergexml": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/mergexml/-/mergexml-1.2.4.tgz",
"integrity": "sha512-yiOlDqcVCz7AG1eSboonc18FTlfqDEKYfGoAV3Lul98u6YRV/s0kjtf4bjk47t0hLTFJR0BSYMd6BpmX3xDjNQ==",
"requires": {
"@xmldom/xmldom": "^0.7.0",
"formidable": "^3.5.1",
"xpath": "0.0.27"
}
},
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@ -2278,11 +2163,6 @@
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz",
"integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg=="
},
"xpath": {
"version": "0.0.27",
"resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz",
"integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ=="
},
"yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",

View File

@ -4,8 +4,8 @@
"description": "ComputerCraft mod virtual lua IDE",
"main": "index.js",
"scripts": {
"dev": "electron src/.",
"nodedev": "node src/."
"dev": "electron .",
"nodedev": "node ."
},
"author": "DPSoftware Foundation",
"license": "GPL-3.0-or-later",
@ -13,13 +13,10 @@
"electron": "^31.1.0"
},
"dependencies": {
"@blockly/field-multilineinput": "^5.0.5",
"@blockly/theme-dark": "^7.0.3",
"@electron/remote": "^2.1.2",
"blockly": "^11.1.1",
"bootstrap": "^5.3.3",
"electron-prompt": "^1.7.0",
"mergexml": "^1.2.4",
"xmldom": "^0.6.0"
}
}

View File

@ -2,7 +2,9 @@ const fs = require('fs');
const path = require('path');
const { DOMParser, XMLSerializer } = require('xmldom');
const peripheralsfolder = path.join(__dirname, "../blocks");
const peripheralsfolder = path.join(__dirname, "../blocks");
let registedblock = {}
function mergeXml(xml1, xml2) {
const parser = new DOMParser();
@ -20,7 +22,6 @@ function mergeXml(xml1, xml2) {
}
const mergedXml = serializer.serializeToString(doc1);
console.log(mergedXml)
return mergedXml;
}
@ -71,8 +72,48 @@ function loadperipheral(workspace, currenttoolbar, peripherals) {
return newxml;
}
function extractFolderName(path) {
// Normalize path separators to handle both Windows and Unix-style paths
const normalizedPath = path.replace(/[\\\/]/g, '/');
// Split by '/' to get path segments
const parts = normalizedPath.split('/');
// Filter out empty parts and get the last segment
const folderName = parts.filter(part => part.trim() !== '').pop();
return folderName;
}
function scanindex() {
const files = fs.readdirSync(peripheralsfolder);
// Iterate through files and directories
files.forEach(file => {
const filePath = path.join(peripheralsfolder, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
// If it's a directory, recursively call scanFolders
const files = fs.readdirSync(filePath);
files.forEach(file => {
if (file === 'index.json') {
const filePath2 = path.join(filePath, file);
// If it's a file named index.json, read its contents
const content = fs.readFileSync(filePath2, 'utf8');
const jsonData = JSON.parse(content);
blockfoldername = extractFolderName(filePath);
registedblock[blockfoldername] = {
infomation: jsonData,
image: null
};
console.log(`registered ${blockfoldername} blocks`)
}
})
}
});
}
module.exports = {
loadperipheral
loadperipheral,
scanindex
}

73
src/frontend.js Normal file
View File

@ -0,0 +1,73 @@
var uploadpopup = document.getElementById('upload-popup');
var aboutpopup = document.getElementById('about-popup');
var librarypopup = document.getElementById('library-popup');
document.addEventListener('DOMContentLoaded', function () {
var tooltips = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
var tooltipList = tooltips.map(function (tooltip) {
return new bootstrap.Tooltip(tooltip);
});
});
// Event listener to close the upload-popup with fade-out effect
document.getElementById('uploadCloseBtn').addEventListener('click', function() {
uploadpopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation
setTimeout(function() {
uploadpopup.style.display = 'none'; // Hide popup after animation completes
uploadpopup.style.animation = ''; // Reset animation property
}, 300); // Adjust to match animation duration in milliseconds
});
document.getElementById('aboutCloseBtn').addEventListener('click', function() {
aboutpopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation
setTimeout(function() {
aboutpopup.style.display = 'none'; // Hide popup after animation completes
aboutpopup.style.animation = ''; // Reset animation property
}, 300); // Adjust to match animation duration in milliseconds
});
document.getElementById('libraryCloseBtn').addEventListener('click', function() {
librarypopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation
setTimeout(function() {
librarypopup.style.display = 'none'; // Hide popup after animation completes
librarypopup.style.animation = ''; // Reset animation property
}, 300); // Adjust to match animation duration in milliseconds
});
//--------------------------------
// Close the upload-popup if the user clicks outside of it
window.addEventListener('click', function(event) {
if (event.target == uploadpopup) {
uploadpopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation
setTimeout(function() {
uploadpopup.style.display = 'none'; // Hide popup after animation completes
uploadpopup.style.animation = ''; // Reset animation property
}, 300); // Adjust to match animation duration in milliseconds
}
});
window.addEventListener('click', function(event) {
if (event.target == aboutpopup) {
aboutpopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation
setTimeout(function() {
aboutpopup.style.display = 'none'; // Hide popup after animation completes
aboutpopup.style.animation = ''; // Reset animation property
}, 300); // Adjust to match animation duration in milliseconds
}
});
window.addEventListener('click', function(event) {
if (event.target == librarypopup) {
librarypopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation
setTimeout(function() {
librarypopup.style.display = 'none'; // Hide popup after animation completes
librarypopup.style.animation = ''; // Reset animation property
}, 300); // Adjust to match animation duration in milliseconds
}
});
function openlibraryselect() {
librarypopup.style.display = 'block';
}

View File

@ -4,28 +4,32 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ccIDE</title>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&display=swap" rel="stylesheet">
<script>
const bootstrap = require('bootstrap')
</script>
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="styles.css" />
</head>
<body>
<!-- Loading screen -->
<div id="loadingScreen">
<p>Loading...</p>
</div>
<!-- Navigation bar -->
<nav id="navbar">
<button class="navbar-button" title="Peripherals" style="background-color: #0087bd;">
<svg viewBox="0 0 24 24"><path d="M15 7v4h1v2h-3V5h2l-3-4-3 4h2v8H8v-2.07c.7-.37 1.2-1.08 1.2-1.93A2.2 2.2 0 0 0 7 6.8c-1.22 0-2.2.98-2.2 2.2 0 .85.5 1.56 1.2 1.93V13a2 2 0 0 0 2 2h3v3.05c-.71.36-1.2 1.1-1.2 1.95a2.2 2.2 0 0 0 2.2 2.2 2.2 2.2 0 0 0 2.2-2.2c0-.85-.49-1.59-1.2-1.95V15h3a2 2 0 0 0 2-2v-2h1V7h-4z" /></svg>
<button class="navbar-button" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="Computer Types" style="background-color: #0087bd;">
<svg viewBox="0 0 24 24"><path d="M6 4h12v1h3v2h-3v2h3v2h-3v2h3v2h-3v2h3v2h-3v1H6v-1H3v-2h3v-2H3v-2h3v-2H3V9h3V7H3V5h3V4m5 11v3h1v-3h-1m2 0v3h1v-3h-1m2 0v3h1v-3h-1z" /></svg>
</button>
<button class="navbar-button" title="Library and Packages" style="background-color: #0087bd;">
<button class="navbar-button" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="Library and Packages" style="background-color: #0087bd;" onclick="openlibraryselect()">
<svg viewBox="0 0 24 24"><path d="M21 16.5c0 .38-.21.71-.53.88l-7.9 4.44c-.16.12-.36.18-.57.18-.21 0-.41-.06-.57-.18l-7.9-4.44A.991.991 0 0 1 3 16.5v-9c0-.38.21-.71.53-.88l7.9-4.44c.16-.12.36-.18.57-.18.21 0 .41.06.57.18l7.9 4.44c.32.17.53.5.53.88v9M12 4.15l-1.89 1.07L16 8.61l1.96-1.11L12 4.15M6.04 7.5 12 10.85l1.96-1.1-5.88-3.4L6.04 7.5M5 15.91l6 3.38v-6.71L5 9.21v6.7m14 0v-6.7l-6 3.37v6.71l6-3.38z" /></svg>
</button>
<button class="navbar-button" title="Disconnect Client" style="background-color: #bd0000; margin-left: auto; position: absolute; right: 65px;" onclick="clientexit()">
<button class="navbar-button" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="Peripherals" style="background-color: #0087bd;">
<svg viewBox="0 0 24 24"><path d="M15 7v4h1v2h-3V5h2l-3-4-3 4h2v8H8v-2.07c.7-.37 1.2-1.08 1.2-1.93A2.2 2.2 0 0 0 7 6.8c-1.22 0-2.2.98-2.2 2.2 0 .85.5 1.56 1.2 1.93V13a2 2 0 0 0 2 2h3v3.05c-.71.36-1.2 1.1-1.2 1.95a2.2 2.2 0 0 0 2.2 2.2 2.2 2.2 0 0 0 2.2-2.2c0-.85-.49-1.59-1.2-1.95V15h3a2 2 0 0 0 2-2v-2h1V7h-4z" /></svg>
</button>
<button class="navbar-button" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="Preview code" style="background-color: #0087bd; margin-left: auto; position: absolute; right: 115px;" onclick="clientexit()">
<svg viewBox="0 0 24 24"><path d="M12 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0 8a5 5 0 0 1-5-5 5 5 0 0 1 5-5 5 5 0 0 1 5 5 5 5 0 0 1-5 5m0-12.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5z" /></svg>
</button>
<button class="navbar-button" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="Disconnect Client" style="background-color: #bd0000; margin-left: auto; position: absolute; right: 65px;" onclick="clientexit()">
<svg viewBox="0 0 24 24"><path d="M19 3H5c-1.11 0-2 .89-2 2v4h2V5h14v14H5v-4H3v4a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2m-8.92 12.58L11.5 17l5-5-5-5-1.42 1.41L12.67 11H3v2h9.67l-2.59 2.58z" /></svg>
</button>
<button class="navbar-button" title="Run" style="background-color: #10bd00; margin-left: auto;" onclick="gencode()">
<button class="navbar-button" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="Run" style="background-color: #10bd00; margin-left: auto;" onclick="gencode()">
<svg viewBox="0 0 24 24"><path d="M8 5.14v14l11-7-11-7z" /></svg>
</button>
</nav>
@ -42,7 +46,7 @@
<div class="popup" id="upload-popup">
<div class="popup-content">
<span class="close" id="uploadCloseBtn">&times;</span>
<button type="button" class="btn-close float-end" aria-label="Close" id="uploadCloseBtn"></button>
<div class="upload-progress-container" style="text-align: center;">
<div class="progress-container">
<div class="progress" id="progress"></div>
@ -64,242 +68,53 @@
</div>
</div>
<style>
#loadingScreen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #212121;
color: #ffffff;
display: flex; /* or display: block; */
align-items: center;
justify-content: center;
font-size: 2em;
z-index: 9999;
visibility: visible; /* Change visibility to hidden */
}
<div class="popup" id="about-popup">
<div class="popup-content">
<button type="button" class="btn-close float-end" aria-label="Close" id="aboutCloseBtn"></button>
<h2>ccIDE</h2>
<p>
ccIDE is an integrated development environment designed for coding Lua scripts
for ComputerCraft. It provides a user-friendly interface for creating and managing
projects, designing custom blocks, and debugging scripts efficiently.
</p>
<p>
Developed by DPSoftware Foundation, ccIDE aims to streamline the development
process for ComputerCraft programmers, offering features like block-based coding,
real-time collaboration, and seamless integration with ComputerCraft environments.
</p>
<p>
Visit <a href="https://damp11113.xyz/dpsoftware/ccide">ccIDE Website</a> for more information and updates.
</p>
<div class="license">
&copy; 2024 DPSoftware Foundation. Licensed under GPL v3.
</div>
<style>
.license {
font-size: 14px;
color: #888;
text-align: center;
margin-top: 20px;
}
</style>
</div>
</div>
:root {
--line-border-fill: #3498db;
--line-border-empty: #e0e0e0;
}
body {
background-color: #212121;
margin: 0;
display: flex;
flex-direction: column;
height: 100vh;
}
#navbar {
background-color: #2c3e50;
color: white;
display: flex;
padding: 15px;
gap: 10px;
}
.navbar-button {
background-color: #2c3e50;
color: white;
border: none;
border-radius: 50%; /* Make the button circular */
width: 40px; /* Adjust size as needed */
height: 40px; /* Adjust size as needed */
font-size: 1em;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
transition: background-color 0.3s;
font-size: 1.5em; /* Adjust size as needed */
}
.navbar-button:hover {
background-color: #34495e; /* Darken color on hover */
}
[data-bs-toggle="tooltip"] {
position: relative; /* Ensure tooltips are positioned correctly */
cursor: pointer; /* Add cursor style for tooltip interaction */
}
#blocklyContainer {
position: relative;
width: 100%;
height: calc(100vh - 10vh); /* Adjust height to accommodate navbar and status bar */
visibility: hidden; /* Initially hide the Blockly container */
}
#blocklyDiv {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#statusBar {
height: 3vh; /* Set the height of the status bar */
background-color: #333;
color: #ffffff;
display: flex;
align-items: center;
padding: 0 10px;
box-sizing: border-box;
}
#statusMessage {
margin: 0;
}
/* Styles for the upload-popup container */
.popup {
display: none; /* Hide initially */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
z-index: 999; /* Ensure it overlays other content */
overflow: auto;
}
/* Styles for the upload-popup content */
.popup-content {
background-color: #fefefe;
margin: 15% auto; /* Center the upload-popup vertically and horizontally */
padding: 20px;
border: 1px solid #888;
width: 80%; /* Adjust width as needed */
max-width: 600px; /* Max width for larger screens */
animation: fadeIn 0.3s ease; /* Fade-in animation */
}
/* Close button */
.close {
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
}
/* Fade-in animation */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* Fade-out animation */
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
.progress-container {
display: flex;
justify-content: space-between;
position: relative;
margin-bottom: 30px;
max-width: 100%;
width: 350px;
}
.progress-container::before {
content: "";
background-color: var(--line-border-empty);
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 100%;
z-index: 99; /* Change z-index to 1 or higher */
}
.progress {
background-color: var(--line-border-fill);
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 0%;
z-index: 101;
transition: 0.4s ease;
}
.progress.error {
background-color: red; /* Set to red color for error state */
}
.circle {
background-color: #fff;
color: #999;
border-radius: 50%;
height: 30px;
width: 30px;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid var(--line-border-empty);
transition: 0.4s ease;
z-index: 101;
}
.circle.active {
border-color: var(--line-border-fill);
}
.circle.error {
border-color: red; /* Optionally, change border color to red */
color: white; /* Optionally, adjust text color for visibility */
}
</style>
<script>
var uploadpopup = document.getElementById('upload-popup');
document.addEventListener('DOMContentLoaded', function () {
var tooltips = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
var tooltipList = tooltips.map(function (tooltip) {
return new bootstrap.Tooltip(tooltip);
});
});
// Event listener to close the upload-popup with fade-out effect
document.getElementById('uploadCloseBtn').addEventListener('click', function() {
uploadpopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation
setTimeout(function() {
uploadpopup.style.display = 'none'; // Hide popup after animation completes
uploadpopup.style.animation = ''; // Reset animation property
}, 300); // Adjust to match animation duration in milliseconds
});
// Close the upload-popup if the user clicks outside of it
window.addEventListener('click', function(event) {
if (event.target == uploadpopup) {
uploadpopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation
setTimeout(function() {
uploadpopup.style.display = 'none'; // Hide popup after animation completes
uploadpopup.style.animation = ''; // Reset animation property
}, 300); // Adjust to match animation duration in milliseconds
}
});
</script>
<div class="popup" id="library-popup">
<div class="popup-content" style="max-width: 600px;">
<button type="button" class="btn-close float-end" aria-label="Close" id="libraryCloseBtn"></button>
<div class="library-container" id="libcontainer">
<div class="library-item overflow-auto">
<img src="image.jpg" class="libimage" onerror="this.onerror=null;this.src='../assets/noimagefallback.png'; this.alt='No Image Available';">
<p>Lib 1</p>
<i>Test</i>
</div>
</div>
<button type="button" class="btn btn-success btn-sm float-end">Import</button>
</div>
</div>
<script src="frontend.js"></script>
<script src="virtualcode.js"></script>
<script src="codegen.js"></script>
</body>

View File

@ -1,4 +1,13 @@
{
"sys_start": {
"message0": "When Code Start",
"message1": "do %1",
"args1": [
{"type": "input_statement", "name": "DO"}
],
"colour": 45,
"tooltip": "Not require but make your code easy to read."
},
"sys_sleep": {
"message0": "Sleep For %1 Second",
"args0": [

View File

@ -9,6 +9,20 @@ if (!luaGenerator.forBlock) {
luaGenerator.forBlock['sys_sleep'] = function(block, generator) {
var sleepfor = generator.valueToCode(block, 'SLEEPSEC', generator.ORDER_OVERRIDES);
var code = `sleep(${sleepfor})`;
var code = `sleep(${sleepfor})\n`;
return code;
};
luaGenerator.forBlock['sys_start'] = function(block, generator) {
var docode = generator.statementToCode(block, 'DO');
var code =
`
function main()
${docode}
end
main()
`
return code;
};

72
src/splash.html Normal file
View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Splash Screen</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #2c3e50;
color: white;
font-family: Arial, sans-serif;
position: relative;
}
#splash-content {
text-align: center;
}
#splash-content img {
width: 100px;
height: 100px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); /* Added drop shadow */
}
.progress-bar {
height: 4px;
background-color: rgba(5, 114, 206, 0.2);
width: 100%;
overflow: hidden;
margin-top: 20px;
}
.progress-bar-value {
width: 100%;
height: 100%;
background-color: rgb(5, 114, 206);
animation: indeterminateAnimation 1s infinite linear;
transform-origin: 0% 50%;
}
@keyframes indeterminateAnimation {
0% {
transform: translateX(0) scaleX(0);
}
40% {
transform: translateX(0) scaleX(0.4);
}
100% {
transform: translateX(100%) scaleX(0.5);
}
}
#copyright {
position: absolute;
bottom: 10px;
left: 10px;
font-size: 12px;
color: #bdc3c7;
}
</style>
</head>
<body>
<div id="splash-content">
<img src="../assets/ccIDEIcon.ico" alt="ccIDE Icon">
<h1>Loading ccIDE...</h1>
<div class="progress-bar">
<div class="progress-bar-value"></div>
</div>
</div>
<div id="copyright">
&copy; 2024 DPSoftware Foundation. Licensed under GPL v3.
</div>
</body>
</html>

190
src/styles.css Normal file
View File

@ -0,0 +1,190 @@
:root {
--line-border-fill: #3498db;
--line-border-empty: #e0e0e0;
}
body {
background-color: #212121;
margin: 0;
display: flex;
flex-direction: column;
height: 100vh;
font-family: 'Noto Sans', sans-serif;
overflow: hidden; /* Hide scrollbars */
}
#navbar {
background-color: #2c3e50;
color: white;
display: flex;
padding: 15px;
gap: 10px;
}
.navbar-button {
background-color: #2c3e50;
color: white;
border: none;
border-radius: 50%; /* Make the button circular */
width: 40px; /* Adjust size as needed */
height: 40px; /* Adjust size as needed */
font-size: 1em;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
transition: background-color 0.3s;
font-size: 1.5em; /* Adjust size as needed */
}
.navbar-button:hover {
background-color: #0066cc; /* Darken color on hover */
z-index: 99;
}
#blocklyContainer {
position: relative;
width: 100%;
height: calc(100vh - 10vh); /* Adjust height to accommodate navbar and status bar */
}
#blocklyDiv {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#statusBar {
height: 3vh; /* Set the height of the status bar */
background-color: #333;
color: #ffffff;
display: flex;
align-items: center;
padding: 0 10px;
box-sizing: border-box;
}
#statusMessage {
margin: 0;
}
/* Styles for the upload-popup container */
.popup {
display: none; /* Hide initially */
position: fixed;
justify-content: center;
align-items: center;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
z-index: 999; /* Ensure it overlays other content */
overflow: auto;
}
/* Styles for the upload-popup content */
.popup-content {
background-color: #fefefe;
margin: 15% auto; /* Center the upload-popup vertically and horizontally */
padding: 20px;
border: 1px solid #888;
width: 80%; /* Adjust width as needed */
max-width: 600px; /* Max width for larger screens */
animation: fadeIn 0.3s ease; /* Fade-in animation */
}
/* Fade-in animation */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* Fade-out animation */
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
.progress-container {
display: flex;
justify-content: space-between;
position: relative;
margin-bottom: 30px;
max-width: 100%;
width: 350px;
}
.progress-container::before {
content: "";
background-color: var(--line-border-empty);
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 100%;
z-index: 99; /* Change z-index to 1 or higher */
}
.progress {
background-color: var(--line-border-fill);
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 0%;
z-index: 101;
transition: 0.4s ease;
}
.progress.error {
background-color: red; /* Set to red color for error state */
}
.circle {
background-color: #fff;
color: #999;
border-radius: 50%;
height: 30px;
width: 30px;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid var(--line-border-empty);
transition: 0.4s ease;
z-index: 101;
}
.circle.active {
border-color: var(--line-border-fill);
}
.circle.error {
border-color: red; /* Optionally, change border color to red */
color: white; /* Optionally, adjust text color for visibility */
}
.libimage {
width: 100px;
height: 100px;
}
.library-item {
margin: 0 auto;
padding: 10px;
}
.library-item:hover {
background-color: #cacaca;
}
.library-container {
border: 1px solid #000000;
}

View File

@ -1,5 +1,5 @@
<xml id="toolbox" style="display: none;">
<category name="Control">
<category name="Control" colour="38">
<block type="sys_sleep">
<value name="SLEEPSEC">
<shadow type="math_number">
@ -44,9 +44,11 @@
</block>
<block type="controls_forEach"></block>
<block type="controls_flow_statements"></block>
</category>
<category name="Math">
<category name="Events" colour="45">
<block type="sys_start"></block>
</category>
<category name="Math" colour="230">
<block type="math_number" gap="32">
<field name="NUM">123</field>
</block>
@ -147,7 +149,7 @@
</value>
</block>
</category>
<category name="Text">
<category name="Text" colour="160">
<block type="text"></block>
<block type="text_join"></block>
<block type="text_append">
@ -249,7 +251,7 @@
</value>
</block>
</category>
<category name="Table">
<category name="Table" colour="260">
<block type="lists_create_with">
<mutation items="0"></mutation>
</block>
@ -302,8 +304,9 @@
<block type="lists_reverse"></block>
</category>
<sep></sep>
<category name="Variables" custom="VARIABLE">
<category name="Variables" custom="VARIABLE" colour="330">
</category>
<category name="Functions" custom="PROCEDURE" colour="290">
</category>
<category name="Functions" custom="PROCEDURE"></category>
<sep></sep>
</xml>

View File

@ -1,4 +1,3 @@
document.getElementById('statusMessage').textContent = "loading";
// override prompt command
window.prompt = function(promptText, defaultValue) {
return ipc.sendSync("prompt", promptText, defaultValue);
@ -7,12 +6,12 @@ window.prompt = function(promptText, defaultValue) {
const fs = require('fs');
const path = require('path');
const { ipcRenderer } = require("electron");
const { loadperipheral } = require("./blocksmanager");
const { loadperipheral, scanindex } = require("./blocksmanager");
const Blockly = require('blockly');
const { DarkTheme } = require('@blockly/theme-dark')
const ipc = ipcRenderer;
let isprojectsaved = false;
let isprojectopened = false;
let usedlibinproject = []
Blockly.utils.colour.setHsvSaturation(0.9)
@ -32,10 +31,8 @@ for (const blockId in blocksJson) {
}
require("./module_generator")
var workspace = Blockly.inject('blocklyDiv', {
toolbox: originaltoolbar,
theme: DarkTheme,
trashcan: true,
grid: {
spacing: 20,
@ -45,11 +42,17 @@ var workspace = Blockly.inject('blocklyDiv', {
}
});
originaltoolbar = loadperipheral(workspace, originaltoolbar, "test");
originaltoolbar = loadperipheral(workspace, originaltoolbar, "IDE");
try {
scanindex();
originaltoolbar = loadperipheral(workspace, originaltoolbar, "Template");
originaltoolbar = loadperipheral(workspace, originaltoolbar, "IDE");
} catch (e) {
ipc.send("erroronstart", `Error on loading block: ${e}`)
}
workspace.getToolbox().getFlyout().autoClose = false;
// Save workspace
ipc.on('save-workspace-request', (event) => {
const state = Blockly.serialization.workspaces.save(workspace);
@ -81,11 +84,16 @@ workspace.addChangeListener(function(event) {
if (isprojectsaved) {
isprojectsaved = false
ipc.send("workspace-notsave")
};
} else if (!isprojectopened) {
ipc.send("workspace-unsave")
}
});
ipc.on('workspace-saved', (event, success) => {
isprojectsaved = success
if (!isprojectopened) {
isprojectopened = true;
}
});
ipc.on('request-undo-redo', (event, redo) => {
@ -93,8 +101,10 @@ ipc.on('request-undo-redo', (event, redo) => {
workspace.undo(redo)
});
// Ensure Blockly container is shown after the workspace is injected
document.getElementById('loadingScreen').style.visibility = 'hidden';
document.getElementById('blocklyContainer').style.visibility = 'visible';
document.getElementById('statusMessage').textContent = "ready";
ipc.on("open-about", () => {
document.getElementById('about-popup').style.display = 'block';
})
// Ensure Blockly container is shown after the workspace is injected
document.getElementById('statusMessage').textContent = "ready";
ipc.send("ready")