Skip to content

Commit e43128b

Browse files
authored
Merge pull request #900 from lmcapacho/develop
Sync and Extend I/O Ports Table Behavior
2 parents 74117e4 + 5d962e9 commit e43128b

3 files changed

Lines changed: 196 additions & 13 deletions

File tree

app/resources/uiThemes/dark/dark.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,3 +980,16 @@
980980
border-color: #666;
981981
color: white;
982982
}
983+
984+
.jexcel_container .highlight {
985+
border: none !important;
986+
border-radius: 0 !important;
987+
width: auto !important;
988+
height: auto !important;
989+
position: static !important;
990+
top: auto !important;
991+
left: auto !important;
992+
padding-top: 0 !important;
993+
994+
background-color: rgba(0, 0, 0, 0.05) !important;
995+
}

app/resources/uiThemes/light/light.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,3 +990,16 @@ li.active {
990990
border-color: #e7e7e7;
991991
color: #333;
992992
}
993+
994+
.jexcel_container .highlight {
995+
border: none !important;
996+
border-radius: 0 !important;
997+
width: auto !important;
998+
height: auto !important;
999+
position: static !important;
1000+
top: auto !important;
1001+
left: auto !important;
1002+
padding-top: 0 !important;
1003+
1004+
background-color: rgba(0, 0, 0, 0.05) !important;
1005+
}

app/scripts/services/forms.js

Lines changed: 170 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ angular
127127
//---------------------------------------------
128128
write(value) {
129129
//-- Write the value to the DOM
130-
$(`#form${this.formId}`).val(value);
130+
$(`#form${this.formId}`).val(value).trigger('input');
131131
}
132132

133133
//------------------------------------------------
@@ -738,6 +738,7 @@ angular
738738
this.tableId = `table${formId}`;
739739
this.table = null;
740740
this.className = className;
741+
this.onEnter = null;
741742

742743
//-- Html template for building the grid
743744
this.htmlTemplate = `
@@ -766,6 +767,12 @@ angular
766767
allowManualInsertRow: false,
767768
tableOverflow: true,
768769
tableHeight: '200px',
770+
contextMenu: false,
771+
onchange: () => {
772+
if (typeof this.onEnter === 'function') {
773+
this.onEnter(this);
774+
}
775+
},
769776
});
770777
}
771778

@@ -776,6 +783,20 @@ angular
776783
read() {
777784
return this.table.getData();
778785
}
786+
787+
allowEnter() {
788+
const editor = document.querySelector(
789+
`#${this.tableId} .editor input`
790+
);
791+
if (editor) {
792+
editor.blur();
793+
if (typeof this.onEnter === 'function') {
794+
this.onEnter(this);
795+
}
796+
return false;
797+
}
798+
return true;
799+
}
779800
}
780801

781802
class Form {
@@ -1023,7 +1044,37 @@ angular
10231044
dialog.setContent(html);
10241045

10251046
//-- Set the callback for the OK button
1026-
dialog.set('onok', callback);
1047+
dialog.set('onok', function (evt) {
1048+
let allow = true;
1049+
1050+
if (Array.isArray(self.fields)) {
1051+
self.fields.forEach((field) => {
1052+
if (
1053+
typeof field.allowEnter === 'function' &&
1054+
!field.allowEnter()
1055+
) {
1056+
allow = false;
1057+
}
1058+
});
1059+
} else {
1060+
Object.keys(self.fields).forEach((tab) => {
1061+
self.fields[tab].forEach((field) => {
1062+
if (
1063+
typeof field.allowEnter === 'function' &&
1064+
!field.allowEnter()
1065+
) {
1066+
allow = false;
1067+
}
1068+
});
1069+
});
1070+
}
1071+
1072+
if (allow) {
1073+
callback(evt);
1074+
} else {
1075+
evt.cancel = true;
1076+
}
1077+
});
10271078

10281079
//-- Set the callback for the Cancel button:
10291080
//-- Do nothing...
@@ -1954,21 +2005,22 @@ angular
19542005
];
19552006

19562007
const columns = [
1957-
{ type: 'text', title: 'Name', width: 150 },
2008+
{ type: 'text', title: 'Name', width: 140 },
19582009
{
19592010
type: 'dropdown',
19602011
title: 'Type',
1961-
width: 70,
2012+
width: 80,
19622013
source: ['IN', 'OUT', 'BIDI'],
19632014
},
19642015
{ type: 'numeric', title: 'Bus width', width: 80 },
19652016
{ type: 'checkbox', title: 'Signed', width: 55 },
19662017
{ type: 'checkbox', title: 'Registered', width: 80 },
19672018
{ type: 'checkbox', title: 'Enable', width: 60 },
19682019
];
1969-
const data = [['', 'IN', 0, false, false, true]];
2020+
const data = [['', 'IN', 1, false, false, true]];
19702021

19712022
let field7 = new GridField(7, 'ports-table', columns, data);
2023+
field7.onEnter = onEnterIOPortsTable;
19722024
this.addField(field7, modulePortsLabel);
19732025

19742026
field0.onChange((value) => {
@@ -2832,13 +2884,104 @@ angular
28322884
//------------------------------------------------------------------------
28332885
//-- Private functions
28342886
//------------------------------------------------------------------------
2887+
function onEnterIOPortsTable(self) {
2888+
const grouped = {
2889+
IN: [],
2890+
OUT: [],
2891+
BIDI: [],
2892+
};
2893+
2894+
self.table.getData().forEach((row) => {
2895+
const enabled = row[5] !== false;
2896+
if (!enabled) {
2897+
return;
2898+
}
2899+
let name = row[0]?.trim();
2900+
const type = row[1]?.toUpperCase();
2901+
const busWidth = parseInt(row[2], 10);
2902+
const signed = row[3] === true;
2903+
2904+
if (!name || !type) {
2905+
return;
2906+
}
2907+
2908+
if (!isNaN(busWidth) && busWidth > 1) {
2909+
name += `[${busWidth - 1}:0]`;
2910+
}
2911+
2912+
if (signed) {
2913+
name = `@${name}`;
2914+
}
2915+
2916+
if (grouped[type]) {
2917+
grouped[type].push(name);
2918+
}
2919+
});
2920+
2921+
const inInput = document.querySelector('#form0');
2922+
const outInput = document.querySelector('#form1');
2923+
const bidiInput1 = document.querySelector('#form3');
2924+
const bidiInput2 = document.querySelector('#form4');
2925+
2926+
inInput.value = grouped.IN.join(', ');
2927+
outInput.value = grouped.OUT.join(', ');
2928+
bidiInput1.value = grouped.BIDI.join(', ');
2929+
bidiInput2.value = grouped.BIDI.join(', ');
2930+
2931+
const coords = self.table.selectedCell || [];
2932+
const row = coords[1] || 0;
2933+
const data = self.table.getData();
2934+
const rowData = self.table.getRowData(row);
2935+
const name = rowData[0];
2936+
const totalRows = data.length;
2937+
2938+
const isEmpty = !name;
2939+
const defaultRow = ['', 'IN', 1, false, false, true];
2940+
2941+
if (isEmpty) {
2942+
const otherEmptyRowExists = data.some((r, i) => !r[0] && i !== row);
2943+
2944+
if (otherEmptyRowExists || totalRows > 1) {
2945+
self.table.deleteRow(row);
2946+
2947+
const stillHasEmptyRow = self.table.getData().some((r) => !r[0]);
2948+
if (!stillHasEmptyRow) {
2949+
self.table.insertRow([...defaultRow]);
2950+
}
2951+
}
2952+
} else {
2953+
const hasEmptyRow = data.some((r) => !r[0]);
2954+
if (!hasEmptyRow) {
2955+
self.table.insertRow([...defaultRow]);
2956+
}
2957+
}
2958+
}
2959+
28352960
function updateIOPortsTable(instance, textList, type) {
2836-
const newNames = textList
2961+
const parsedNames = textList
28372962
.split(',')
2838-
.map((n) => n.trim())
2839-
.filter((n) => n !== '');
2963+
.map((n) => {
2964+
let trimmed = n.trim();
2965+
let signed = false;
2966+
2967+
if (trimmed.startsWith('@')) {
2968+
signed = true;
2969+
trimmed = trimmed.slice(1);
2970+
}
28402971

2841-
const defaultRow = ['', 'IN', 0, false, false, true];
2972+
const match = trimmed.match(/^(\w+)\[(\d+):(\d+)\]$/);
2973+
if (match) {
2974+
const name = match[1];
2975+
const msb = parseInt(match[2], 10);
2976+
const lsb = parseInt(match[3], 10);
2977+
const busWidth = Math.abs(msb - lsb) + 1;
2978+
return { name, busWidth, signed };
2979+
}
2980+
return { name: trimmed, busWidth: 1, signed };
2981+
})
2982+
.filter(({ name }) => name !== '');
2983+
2984+
const defaultRow = ['', 'IN', 1, false, false, true];
28422985
const data = instance.getData();
28432986

28442987
const nameToRowIndex = new Map();
@@ -2851,13 +2994,18 @@ angular
28512994
}
28522995
});
28532996

2854-
newNames.forEach((name) => {
2997+
const newNames = parsedNames.map((p) => p.name);
2998+
parsedNames.forEach(({ name, busWidth, signed }) => {
28552999
if (nameToRowIndex.has(name)) {
28563000
const i = nameToRowIndex.get(name);
28573001
const row = instance.getData()[i];
28583002
if (row[1] !== type) {
28593003
instance.setValueFromCoords(1, i, type);
28603004
}
3005+
if (row[2] !== busWidth) {
3006+
instance.setValueFromCoords(2, i, busWidth);
3007+
}
3008+
instance.setValueFromCoords(3, i, signed);
28613009
usedIndexes.add(i);
28623010
} else {
28633011
let reused = false;
@@ -2870,13 +3018,15 @@ angular
28703018
existingName
28713019
) {
28723020
instance.setValueFromCoords(0, i, name);
3021+
instance.setValueFromCoords(2, i, busWidth);
3022+
instance.setValueFromCoords(3, i, signed);
28733023
usedIndexes.add(i);
28743024
reused = true;
28753025
break;
28763026
}
28773027
}
28783028
if (!reused) {
2879-
instance.insertRow([name, type, 0, false, false, true]);
3029+
instance.insertRow([name, type, busWidth, signed, false, true]);
28803030
}
28813031
}
28823032
});
@@ -2889,13 +3039,20 @@ angular
28893039
}
28903040

28913041
const updated = instance.getData();
3042+
let hasEmptyRow = false;
3043+
28923044
for (let i = updated.length - 1; i >= 0; i--) {
2893-
if (!updated[i][0]) {
3045+
const length = instance.getData().length;
3046+
if (!updated[i][0] && length > 1) {
28943047
instance.deleteRow(i);
3048+
} else if (!updated[i][0]) {
3049+
hasEmptyRow = true;
28953050
}
28963051
}
28973052

2898-
instance.insertRow([...defaultRow]);
3053+
if (!hasEmptyRow) {
3054+
instance.insertRow([...defaultRow]);
3055+
}
28993056
}
29003057
}
29013058
);

0 commit comments

Comments
 (0)