Справица:DiagramGenerator.js — разлика између измена

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу
(Spravica u testiranju; nekome možda bude korisna)
 
м (Podela spravice na module; ovo je sad modul sa korisničkim interfejsom za generisanje dijagrama)
Ред 1: Ред 1:
/* eslint {"max-statements": ["error", 100]} */
(function() {
(function() {
     'use strict';
     'use strict';
    var lib = mw.libs.diagramGenerator;
     var fileContents = {};
     var fileContents = {};
    var signals = [
        'MOST1_2',
        'MOST1_3',
        'MOST2_1',
        'MOST3_2',
        'rdCPU',
        'wrCPU',
        'ldMDR',
        'mxMDR',
        'MDRout1',
        'eMDR',
        'ldMAR',
        'incMAR',
        'eMAR',
        'ldDWL',
        'ldDWH',
        'DWout2',
        'wrGPR',
        'GPRout1',
        'ldGPRAR',
        'incGPRAR',
        'ldSP',
        'SPout2',
        'incSP',
        'DECSP',
        'ldCW',
        'CWout3',
        'ADDout2',
        'ldPC',
        'incPC',
        'PCHout3',
        'PCLout3',
        'PCout1',
        'ldIR0',
        'ldIR1',
        'ldIR2',
        'ldIR3',
        'IRPOMout3',
        'IRJAout2',
        'IRDAout3',
        'IRBRout3',
        'add',
        'sub',
        'inc',
        'dec',
        'and',
        'or',
        'xor',
        'not',
        'ALUout1',
        'ldAB',
        'ABout3',
        'shr',
        'shl',
        'ldBB',
        'BBout2',
        'ldAW',
        'AWout3',
        'AWHout3',
        'ldBW',
        'BWout2',
        'ldPSWH',
        'ldPSWL',
        'ldN',
        'ldZ',
        'ldC',
        'ldV',
        'ldL',
        'stPSWI',
        'clPSWI',
        'stPSWT',
        'clPSWT',
        'PSWHout3',
        'PSWLout3',
        'clSTART',
        'ldIMR',
        'IMRout2',
        'ldBR',
        'IVTDSPout3',
        'ldIVTP',
        'IVTPout1',
        'UINTout3',
        'UEXTout3',
        'stPRCOD',
        'stPRADR',
        'stPRINS',
        'clPRCOD',
        'clPRADR',
        'clPRINS',
        'clPRINM',
        'clINTR',
        'stPSWR',
        'clPSWR'
    ];
    var BranchType = {
        NONE: 'none',
        CONDITIONAL: 'conditional',
        UNCONDITIONAL: 'unconditional',
        BRADR: 'bradr',
        BROPR: 'bropr'
    };
    var CONDITIONAL_BRANCH = /^br\s*\(\s*if\s+(\S+)\s+then\s+(\S+)\s*\)$/;
    var UNCONDITIONAL_BRANCH = /^br\s+(\S+)$/;
    var MAX_LINE_LENGTH = 22;
    var FIELDS = [
        ['Ime i prezime', 'Indeks', 'Potpis'],
        ['Naziv', 'Datum', 'Strana']
    ];


     function updateSubmitEnabled() {
     function updateSubmitEnabled() {
Ред 138: Ред 30:
     }
     }


     function parseConfig(config) {
     function downloadSVG(svg) {
         try {
         var contents = [
             return config.split('\n').map(function(line) {
             '<?xml version="1.0" encoding="utf-8"?>',
                return line.replace(/\/\/.*/g, '').trim();
            '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">',
             }).filter(Boolean).map(function(line) {
            svg.outerHTML
                return JSON.parse('[' + line + ']');
        ].join('\n');
            });
        var blob = new Blob([contents], {
         } catch (error) {
             type: 'image/svg+xml'
            console.error(error);
        });
            return null;
        var blobUrl = URL.createObjectURL(blob);
        }
        var downloadLink = document.createElement('a');
        downloadLink.href = blobUrl;
        downloadLink.download = 'Diagram.svg';
        document.body.appendChild(downloadLink);
         downloadLink.click();
        URL.revokeObjectURL(blobUrl);
        downloadLink.remove();
     }
     }


     function findConfig(config, prefix) {
     function printPages(width, height, pages) {
         return config.filter(function(line) {
         var imageWindow = window.open('');
             return !line.slice(0, prefix.length).some(function(value, index) {
        pages.forEach(function(page) {
                return value !== prefix[index];
             var svg = lib.createSVG(width, height);
             });
            svg.appendChild(page);
        }).map(function(line) {
            svg.style.breakAfter = 'page';
            return line.slice(prefix.length);
             imageWindow.document.write(svg.outerHTML);
         });
         });
        imageWindow.document.close();
        imageWindow.focus();
        imageWindow.print();
     }
     }


     function prepareLine(line) {
     function postGeneration(parameters, actionId, pages) {
        return line
         switch (actionId) {
            .toLowerCase()
             case 'diagram-generator-this-page':
            .replace(/\(/g, ' ( ')
                var svg = lib.createSVGWithPages(parameters.width, parameters.height, pages);
            .replace(/\)/g, ' ) ')
                $('#diagram-generator-result').html(svg.outerHTML);
            .replace(/\s+/g, ' ')
            .replace(/if !/g, 'if #')
            .replace(/(.*?)!.*/g, '$1')
            .replace(/(.*?);.*/, '$1')
            .replace(/\t/g, ' ')
            .replace(/\s+:/g, ': ')
            .replace(/\s+/g, ' ')
            .trim();
    }
 
    function parseAddress(line) {
         if (line === '') {
             return -1;
        }
        var addressLine = line.split(' ')[0];
        if (addressLine.endsWith(':') || !addressLine.startsWith('madr')) {
            return -1;
        }
        var address = parseInt(addressLine.substring(4), 16);
        if (isNaN(address)) {
            return -1;
        }
        return address;
    }
 
    function parseLabels(line) {
        var labels = [];
        var splitLine = line.split(' ');
        for (var i = 0, l = splitLine.length; i < l; ++i) {
            if (!splitLine[i].endsWith(':')) {
                 break;
                 break;
             }
             case 'diagram-generator-new-page':
            var label = splitLine[i].slice(0, -1);
                 printPages(parameters.width, parameters.height, pages);
            if (!labels.includes(label)) {
                labels.push(label);
            }
        }
        return labels;
    }
 
    function parseConditions(config) {
        return findConfig(config, ['CONTRODC']).filter(function(option) {
            return option[1];
        }).map(function(option) {
            var segments = option[1].split('.');
            return option[2] + segments[segments.length - 1].toLowerCase();
        });
    }
 
    function parseLine(comment, line, config) {
        var preparedLine = prepareLine(line);
        var instruction = {
            address: parseAddress(preparedLine),
            comment: comment,
            line: line
        };
        var unparsedLine = preparedLine;
        if (instruction.address >= 0) {
            unparsedLine = unparsedLine.split(' ').slice(1).join(' ');
        }
        instruction.labels = parseLabels(unparsedLine);
        instruction.signals = [];
        instruction.branchType = BranchType.NONE;
        unparsedLine = unparsedLine.split(' ').slice(instruction.labels.length).join(' ');
        var hadBranch = false;
        var conditions = parseConditions(config);
        unparsedLine.split(',').map(function(segment) {
            return segment.trim();
        }).forEach(function(arg) {
            var isBropr = arg === 'bropr';
            var isBradr = arg === 'bradr';
            var isAddressBranch = arg.includes('br ');
            var isConditional = arg.includes('if ');
            var isBranch = isBropr || isBradr || isAddressBranch;
            var isSignal = signals.find(function(signal) {
                return signal.toLowerCase() === arg;
            });
            // Check for multiple branches.
            if (isBranch && hadBranch) {
                instruction.error = 'More than one branch';
            } else if (isBranch) {
                hadBranch = true;
            }
            // Set relevant instruction fields.
            var res;
            if (isSignal) {
                if (!instruction.signals.includes(arg)) {
                    instruction.signals.push(arg);
                }
            } else if (isBropr) {
                instruction.branchType = BranchType.BROPR;
            } else if (isBradr) {
                instruction.branchType = BranchType.BRADR;
            } else if (isBranch && isConditional) {
                res = CONDITIONAL_BRANCH.exec(arg);
                if (!res) {
                    instruction.error = 'Invalid conditional branch format';
                    return;
                }
                instruction.branchType = BranchType.CONDITIONAL;
                var splitCondition = res[1].split('.');
                var complement = res[1].startsWith('#') && splitCondition.length > 1 ? '#' : '';
                instruction.condition = complement + splitCondition[splitCondition.length - 1];
                if (!conditions.includes(instruction.condition)) {
                    instruction.error = 'Unknown condition code ' + instruction.condition;
                    return;
                }
                instruction.destination = res[2];
                // TODO: Destination validation
            } else if (isBranch && !isConditional) {
                res = UNCONDITIONAL_BRANCH.exec(arg);
                if (!res) {
                    instruction.error = 'Invalid unconditional branch format';
                    return;
                }
                instruction.branchType = BranchType.UNCONDITIONAL;
                instruction.destination = res[1];
                // TODO: Destination validation
            } else {
                instruction.error = 'Unknown operation ' + arg;
            }
        });
        return instruction;
    }
 
    function createRect(startX, startY, width, height) {
        var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
        rect.setAttributeNS('http://www.w3.org/2000/svg', 'x', startX);
        rect.setAttributeNS('http://www.w3.org/2000/svg', 'y', startY);
        rect.setAttributeNS('http://www.w3.org/2000/svg', 'width', width);
        rect.setAttributeNS('http://www.w3.org/2000/svg', 'height', height);
        rect.setAttributeNS('http://www.w3.org/2000/svg', 'stroke-width', '1');
        rect.setAttributeNS('http://www.w3.org/2000/svg', 'fill-opacity', '0');
        rect.style.stroke = 'black';
        return rect;
    }
 
    function createConditionRect(startX, startY, width, height) {
        var rect = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
        var points = [
            [startX, startY + height / 2],
            [startX + width * 1 / 20, startY],
            [startX + width * 19 / 20, startY],
            [startX + width, startY + height / 2],
            [startX + width * 19 / 20, startY + height],
            [startX + width * 1 / 20, startY + height]
        ];
        rect.setAttributeNS('http://www.w3.org/2000/svg', 'points', points.map(function(point) {
            return point.join(',');
        }).join(' '));
        rect.style.fill = 'transparent';
        rect.style.stroke = 'black';
        return rect;
    }
 
    function createTextLine(x, y, text) {
        var line = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
        line.textContent = text;
        line.setAttributeNS('http://www.w3.org/2000/svg', 'x', x);
        line.setAttributeNS('http://www.w3.org/2000/svg', 'y', y);
        return line;
    }
 
    function wrapText(textSegments, maxLineLength) {
        var lines = [];
        var currentLine = '';
        textSegments.forEach(function(segment, index) {
            var segmentWithComma = segment.trim();
            if (index !== textSegments.length - 1) {
                 segmentWithComma += ', ';
            }
            if (segmentWithComma.length + currentLine.length > maxLineLength && currentLine.length > 0) {
                lines.push(currentLine);
                currentLine = '';
            }
            currentLine += segmentWithComma;
        });
        lines.push(currentLine);
        return lines;
    }
 
    function createText(startX, startY, line) {
        var lines = typeof line === 'string' ? [line] : line;
        var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
        text.setAttributeNS('http://www.w3.org/2000/svg', 'x', startX);
        text.setAttributeNS('http://www.w3.org/2000/svg', 'y', startY);
        text.setAttributeNS('http://www.w3.org/2000/svg', 'alignment-baseline', 'middle');
        text.setAttributeNS('http://www.w3.org/2000/svg', 'font-family', 'monospace');
        text.setAttributeNS('http://www.w3.org/2000/svg', 'text-anchor', 'middle');
        lines.forEach(function(currentLine, index) {
            text.appendChild(createTextLine(startX, startY + index * 15, currentLine));
        });
        return text;
    }
 
    function createTextNotCentered(startX, startY, text) {
        var textNode = createText(startX, startY, text);
        textNode.removeAttribute('text-anchor');
        return textNode;
    }
 
    function createLine(startX, startY, endX, endY) {
        var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
        line.setAttributeNS('http://www.w3.org/2000/svg', 'x1', startX);
        line.setAttributeNS('http://www.w3.org/2000/svg', 'y1', startY);
        line.setAttributeNS('http://www.w3.org/2000/svg', 'x2', endX);
        line.setAttributeNS('http://www.w3.org/2000/svg', 'y2', endY);
        line.style.stroke = 'black';
        return line;
    }
 
    function createArrow(startX, startY, endX, endY) {
        var arrow = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
        var points = [[endX, endY], [endX, endY], [endX, endY]];
        if (startX === endX) {
            // Vertical
            points[0][0] -= 2.5;
            points[1][0] += 2.5;
            if (endY > startY) {
                // Down
                points[0][1] -= 2.5;
                points[1][1] -= 2.5;
            } else {
                // Up
                points[0][1] += 2.5;
                points[1][1] += 2.5;
            }
        } else {
            // Horizontal
            points[0][1] -= 2.5;
            points[1][1] += 2.5;
            if (endX > startX) {
                // Right
                points[0][0] -= 2.5;
                points[1][0] -= 2.5;
            } else {
                // Left
                points[0][0] += 2.5;
                points[1][0] += 2.5;
            }
        }
        arrow.setAttributeNS('http://www.w3.org/2000/svg', 'points', points.map(function(point) {
            return point.join(',');
        }).join(' '));
        arrow.style.fill = 'black';
        var group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
        group.appendChild(createLine(startX, startY, endX, endY));
        group.appendChild(arrow);
        return group;
    }
 
    function hasSelfBranch(instruction) {
        if (instruction.destination.startsWith('madr')) {
            return parseInt(instruction.destination.substring(4), 16) === instruction.address;
        }
        return instruction.labels.includes(instruction.destination);
    }
 
    function generateInstructionDiagram(parameters, instruction, currentY) {
        var y = currentY;
        var arrowHeight = parameters.arrowHeight;
        var group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
        var columnWidth = (parameters.width - 2 * parameters.margin) / 3;
        var columnOffset = (columnWidth - 200 - 100 - 20) / 2;
        var offL = parameters.margin + columnOffset;
        var offM = offL + columnWidth;
        var offR = offM + columnWidth;
        // Label
        if (instruction.labels.length > 0) {
            // TODO: Support more than one label and also label wrapping
            group.appendChild(createRect(offM + 220, y, 100, 27.5));
            group.appendChild(createRect(offL + 220, y, 100, 27.5));
            group.appendChild(createText(offM + 270, y + 17.5, instruction.labels[0]));
            group.appendChild(createText(offL + 270, y + 17.5, instruction.labels[0]));
            group.appendChild(createArrow(offM + 220, y + 13.75, offM + 200, y + 13.75));
            group.appendChild(createArrow(offL + 220, y + 13.75, offL + 200, y + 13.75));
        }
        // Signals
        var wrappedTextMiddle = wrapText(instruction.signals, MAX_LINE_LENGTH);
        // TODO: Translate signals
        var wrappedTextLeft = wrapText(instruction.signals, MAX_LINE_LENGTH);
        var wrappedTextRight = wrapText(instruction.line.split(','), columnWidth / 10);
        var yDiffLeft = (wrappedTextLeft.length - 1) * 15 + 17.5;
        var yDiffMiddle = (wrappedTextMiddle.length - 1) * 15 + 17.5;
        var yDiff = Math.max(yDiffLeft, yDiffMiddle);
        group.appendChild(createText(offM + 100, y + 17.5, wrappedTextMiddle));
        group.appendChild(createText(offL + 100, y + 17.5, wrappedTextLeft));
        group.appendChild(createTextNotCentered(offR, y + 17.5, wrappedTextRight));
        var rectHeight = yDiff + 10;
        group.appendChild(createRect(offM, y, 200, rectHeight));
        group.appendChild(createRect(offL, y, 200, rectHeight));
        group.appendChild(createArrow(offM + 100, y + rectHeight, offM + 100, y + rectHeight + arrowHeight));
        group.appendChild(createArrow(offL + 100, y + rectHeight, offL + 100, y + rectHeight + arrowHeight));
        y += rectHeight + arrowHeight;
        // Condition
        switch (instruction.branchType) {
            case BranchType.BRADR:
            case BranchType.BROPR:
                group.appendChild(createText(offM + 100, y + 17.5, instruction.branchType));
                group.appendChild(createText(offL + 100, y + 17.5, instruction.branchType));
                group.appendChild(createConditionRect(offM, y, 200, 27.5));
                group.appendChild(createConditionRect(offL, y, 200, 27.5));
                y += 50;
                 break;
                 break;
             case BranchType.CONDITIONAL:
             case 'diagram-generator-download-svg':
                group.appendChild(createText(offM + 100, y + 17.5, instruction.condition));
                 downloadSVG(lib.createSVGWithPages(parameters.width, parameters.height, pages));
                group.appendChild(createText(offL + 100, y + 17.5, instruction.condition));
                group.appendChild(createConditionRect(offM, y, 200, 27.5));
                group.appendChild(createConditionRect(offL, y, 200, 27.5));
                group.appendChild(createArrow(offM + 100, y + 27.5, offM + 100, y + 27.5 + arrowHeight));
                group.appendChild(createArrow(offL + 100, y + 27.5, offL + 100, y + 27.5 + arrowHeight));
                group.appendChild(createText(offM + 90, y + 27.5 + arrowHeight * 3 / 4, '0'));
                group.appendChild(createText(offL + 90, y + 27.5 + arrowHeight * 3 / 4, '0'));
                group.appendChild(createText(offM + 203, y + 10, '1'));
                group.appendChild(createText(offL + 203, y + 10, '1'));
                if (hasSelfBranch(instruction)) {
                    group.appendChild(createLine(offM + 200, y + 13.75, offM + 210, y + 13.75));
                    group.appendChild(createLine(offL + 200, y + 13.75, offL + 210, y + 13.75));
                    group.appendChild(createLine(offM + 210, y + 13.75, offM + 210, y - 20));
                    group.appendChild(createLine(offL + 210, y + 13.75, offL + 210, y - 20));
                    group.appendChild(createLine(offM + 210, y + 13.75, offM + 210, y - 20));
                    group.appendChild(createLine(offL + 210, y + 13.75, offL + 210, y - 20));
                    group.appendChild(createArrow(offM + 210, y - 20, offM + 200, y - 20));
                    group.appendChild(createArrow(offL + 210, y - 20, offL + 200, y - 20));
                } else {
                    group.appendChild(createArrow(offM + 200, y + 13.75, offM + 220, y + 13.75));
                    group.appendChild(createArrow(offL + 200, y + 13.75, offL + 220, y + 13.75));
                    group.appendChild(createRect(offM + 220, y, 100, 27.5));
                    group.appendChild(createRect(offL + 220, y, 100, 27.5));
                    group.appendChild(createText(offM + 270, y + 17.5, instruction.destination));
                    group.appendChild(createText(offL + 270, y + 17.5, instruction.destination));
                }
                y += 27.5 + arrowHeight;
            break;
            case BranchType.UNCONDITIONAL:
                 // TODO: Support label wrapping
                group.appendChild(createRect(offM + 50, y, 100, 27.5));
                group.appendChild(createRect(offL + 50, y, 100, 27.5));
                group.appendChild(createText(offM + 100, y + 17.5, instruction.destination));
                group.appendChild(createText(offL + 100, y + 17.5, instruction.destination));
                y += 40;
                 break;
                 break;
             default:
             default:
                 // Do nothing.
                 // ???
                 break;
                 break;
         }
         }
        var separator = createLine(parameters.margin, y, parameters.width - parameters.margin, y);
        separator.setAttributeNS('http://www.w3.org/2000/svg', 'stroke-dasharray', '10,10');
        group.appendChild(separator);
        return [group, y];
    }
    function createPage(parameters, instructions) {
        var group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
        var width = parameters.width;
        var height = parameters.height;
        var margin = parameters.margin;
        var headerHeight = parameters.headerHeight;
        var footerRowHeight = parameters.footerRowHeight;
        var pageWidth = width - 2 * margin;
        var columnWidth = pageWidth / 3;
        var columnHalfWidth = columnWidth / 2;
        group.append(createLine(margin, margin, width - margin, margin));
        group.append(createLine(margin, margin, margin, height - margin));
        group.append(createLine(width - margin, margin, width - margin, height - margin));
        group.append(createLine(margin, height - margin, width - margin, height - margin));
        group.append(createLine(margin, margin + headerHeight, width - margin, margin + headerHeight));
        group.append(createLine(margin, margin + headerHeight, width - margin, margin + headerHeight));
        group.append(createLine(margin + columnWidth, margin, margin + columnWidth, height - margin));
        group.append(createLine(margin + columnWidth * 2, margin, margin + columnWidth * 2, height - margin));
        group.append(createText(margin + columnHalfWidth, margin + 15, 'Dijagram toka mikrooperacija'));
        group.append(createText(margin + columnHalfWidth * 3, margin + 15, 'Dijagram toka upravljačkih signala'));
        group.append(createText(margin + columnHalfWidth * 5, margin + 15, 'Sekvenca upravljačkih signala'));
        var lowerRowMargin = height - margin - footerRowHeight;
        var upperRowMargin = lowerRowMargin - footerRowHeight;
        group.append(createLine(margin, lowerRowMargin, width - margin, lowerRowMargin));
        group.append(createLine(margin, upperRowMargin, width - margin, upperRowMargin));
        var pageHeight = height - 2 * margin - FIELDS.length * footerRowHeight;
        var currentY = margin + headerHeight;
        pageHeight -= currentY;
        while (pageHeight > 0 && instructions.length > 0) {
            var instruction = instructions.shift();
            var generationResult = generateInstructionDiagram(parameters, instruction, currentY);
            var heightDiff = generationResult[1] - currentY;
            currentY = generationResult[1];
            pageHeight -= heightDiff;
            if (pageHeight >= 0) {
                group.appendChild(generationResult[0]);
            } else {
                instructions.unshift(instruction);
            }
        }
        FIELDS.forEach(function(row, rowIndex) {
            row.forEach(function(cell, columnIndex) {
                var textX = margin + columnIndex * columnWidth + 10;
                var textY = height - margin - (FIELDS.length - rowIndex - 0.5) * footerRowHeight;
                group.append(createTextNotCentered(textX, textY, cell + ':'));
            });
        });
        return group;
     }
     }


     function generate(event) {
     function getParameters() {
         event.preventDefault();
         return {
        $('#diagram-generator-error').text('');
        var newPage = $('#diagram-generator-new-page').prop('checked');
        var instructions = [];
        var comment = '';
        var config = parseConfig(fileContents.configuration);
        if (!config) {
            $('#diagram-generator-error').text('Error while parsing configuration.');
            return;
        }
        var lines = fileContents.microcode.split('\n');
        var labels = {};
        for (var i = 0, l = lines.length; i < l; ++i) {
            var line = lines[i].trim();
            if (!line) {
                continue;
            }
            if (line.startsWith('!')) {
                comment = line;
            } else {
                var instruction = parseLine(comment, line, config);
                comment = '';
                for (var j = 0, l2 = instruction.labels.length; j < l2; ++j) {
                    var label = instruction.labels[j];
                    if (labels[label]) {
                        instruction.error = 'Duplicate label ' + label;
                        break;
                    }
                    labels[label] = instruction.address;
                }
                if (instruction.error) {
                    $('#diagram-generator-error').text('Microcode error: ' + instruction.error + ' at line ' + (i + 1));
                    return;
                }
                instructions.push(instruction);
            }
        }
        var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
        var parameters = {
             arrowHeight: 15,
             arrowHeight: 15,
            columnHeaderLeft: 'Dijagram toka mikrooperacija',
            columnHeaderMiddle: 'Dijagram toka upravljačkih signala',
            columnHeaderRight: 'Sekvenca upravljačkih signala',
             headerHeight: 20,
             headerHeight: 20,
             height: 1680,
             height: 1680,
Ред 618: Ред 95:
             width: 1200
             width: 1200
         };
         };
         var height = parameters.height;
    }
         svg.setAttributeNS('http://www.w3.org/2000/svg', 'width', parameters.width);
 
         var numPages = 0;
    function generate(event) {
         while (instructions.length > 0) {
         event.preventDefault();
             var page = createPage(parameters, instructions);
         $('#diagram-generator-error').text('');
            page.setAttributeNS('http://www.w3.org/2000/svg', 'transform', 'translate(0, ' + numPages * height + ')');
         var config = lib.parseConfig(fileContents.configuration);
            svg.appendChild(page);
         if (!config) {
             ++numPages;
             $('#diagram-generator-error').text('Error while parsing configuration.');
             return;
         }
         }
         var pageNodes = svg.children;
         var instructionsResult = lib.getInstructions(config, fileContents.microcode);
        var numFieldRows = FIELDS.length;
         if (instructionsResult.error) {
        var numFieldColumns = FIELDS[0].length;
             $('#diagram-generator-error').text(instructionsResult.error);
        var numFields = numFieldRows * numFieldColumns;
        for (var pageIndex = 0; pageIndex < numPages; ++pageIndex) {
            var fieldNodes = Array.prototype.slice.call(pageNodes[pageIndex].children, -numFields);
            var fields = [];
            for (var rowIndex = 0; rowIndex < numFieldRows; ++rowIndex) {
                var fieldRow = [];
                for (var columnIndex = 0; columnIndex < numFieldColumns; ++columnIndex) {
                    fieldRow.push(fieldNodes[rowIndex * numFieldColumns + columnIndex]);
                }
                fields.push(fieldRow);
            }
            var today = new Date();
            var formattedDate = today.getDate() + '. ' + (today.getMonth() + 1) + '. ' + today.getFullYear() + '.';
            fields[0][0].textContent += ' ' + parameters.nameSurname;
            fields[0][1].textContent += ' ' + parameters.indexNum;
            fields[1][0].textContent += ' ' + parameters.subjectName;
            fields[1][1].textContent += ' ' + formattedDate;
            fields[1][2].textContent += ' ' + (pageIndex + 1) + '/' + numPages;
        }
        var totalHeight = numPages * height;
        svg.setAttributeNS('http://www.w3.org/2000/svg', 'height', totalHeight);
        svg.setAttributeNS('http://www.w3.org/2000/svg', 'viewBox', '0 0 ' + parameters.width + ' ' + totalHeight);
        svg.setAttributeNS('http://www.w3.org/2000/svg', 'version', '1.1');
        svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
        svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
         if (newPage) {
            var imageWindow = window.open('');
            imageWindow.document.write(svg.outerHTML);
        } else {
             $('#diagram-generator-result').html(svg.outerHTML);
         }
         }
        var instructions = instructionsResult.result;
        var parameters = getParameters();
        var pages = lib.getPages(parameters, config, instructions);
        postGeneration(parameters, event.currentTarget.id, pages);
    }
    function createFieldset(text, contents) {
        var $icon = $('<span>').addClass([
            'oo-ui-widget',
            'oo-ui-widget-enabled',
            'oo-ui-iconElement-icon',
            'oo-ui-iconElement',
            'oo-ui-labelElement-invisible',
            'oo-ui-iconWidget'
        ]);
        return $('<fieldset>', {
            html: [
                $('<legend>', {
                    html: [
                        $('<span>', {
                            'class': 'oo-ui-labelElement-label',
                            'text': text
                        }),
                        $icon.clone().addClass('oo-ui-icon-expand'),
                        $icon.clone().addClass('oo-ui-icon-collapse')
                    ],
                    role: 'button',
                    tabindex: 0
                }).addClass(['oo-ui-fieldsetLayout-header', 'mw-collapsible-toggle']),
                $('<div>', {
                    'class': 'oo-ui-fieldsetLayout-group',
                    'html': $('<div>', {
                        'class': 'oo-ui-widget oo-ui-widget-enabled',
                        'html': contents
                    })
                })
            ]
        }).addClass([
            'oo-ui-layout',
            'oo-ui-labelElement',
            'oo-ui-fieldsetLayout',
            'mw-collapsible',
            'mw-made-collapsible'
        ]);
    }
    function createFormRow(text, options) {
        var inputOptions = $.extend({}, options, {
            'class': 'oo-ui-inputWidget-input',
            'name': options.id
        });
        return $('<div>', {
            html: $('<div>', {
                'class': 'oo-ui-fieldLayout-body',
                'html': [
                    $('<span>', {
                        'class': 'oo-ui-fieldLayout-header',
                        'html': $('<label>', {
                            'class': 'oo-ui-labelElement-label',
                            'for': options.id,
                            'text': text + ':'
                        })
                    }),
                    $('<div>', {
                        'class': 'oo-ui-fieldLayout-field',
                        'html': $('<div>', {
                            html: $('<input>', inputOptions)
                        }).addClass([
                            'oo-ui-widget',
                            'oo-ui-widget-enabled',
                            'oo-ui-inputWidget',
                            'oo-ui-textInputWidget',
                            'oo-ui-textInputWidget-type-text'
                        ])
                    })
                ]
            })
        }).addClass([
            'mw-htmlform-field-HTMLTextField',
            'oo-ui-layout',
            'oo-ui-labelElement',
            'oo-ui-fieldLayout',
            'oo-ui-fieldLayout-align-top'
        ]);
    }
    function createFormButton(text, options) {
        return $('<span>', $.extend({
            'class': [
                'oo-ui-buttonElement',
                'oo-ui-buttonElement-framed',
                'oo-ui-flaggedElement-primary',
                'oo-ui-flaggedElement-progressive',
                'oo-ui-labelElement',
                'oo-ui-widget-enabled'
            ].join(' ')
        }, options)).append(
            $('<button>', {
                'class': 'oo-ui-buttonElement-button',
                'tabindex': '0'
            }).append(
                $('<span>', {
                    'class': 'oo-ui-labelElement-label label',
                    'text': text
                })
            )
        );
     }
     }


     function init() {
     function init() {
         $('#diagram-generator').append(
        var $optionsFieldset = createFieldset('Options', [
            createFormRow('Microcode', {
                change: updateFile,
                id: 'microcode',
                type: 'file'
            }),
            createFormRow('Configuration', {
                change: updateFile,
                id: 'configuration',
                type: 'file'
            }),
            createFormRow('Student name', {
                id: 'diagram-generator-student-name',
                placeholder: 'Pera Pisar',
                type: 'text'
            }),
            createFormRow('Student index', {
                id: 'diagram-generator-student-index',
                placeholder: '2021/0000',
                type: 'text'
            })
        ]);
        var $actionsFieldset = createFieldset('Actions', [
            createFormButton('Generate (on page)', {
                click: generate,
                id: 'diagram-generator-this-page'
            }),
            createFormButton('Print (new page)', {
                click: generate,
                id: 'diagram-generator-new-page'
            }),
            createFormButton('Download SVG', {
                click: generate,
                id: 'diagram-generator-download-svg'
            })
        ]);
         $('#diagram-generator').addClass([
            'mw-htmlform-ooui-wrapper',
            'oo-ui-layout',
            'oo-ui-panelLayout',
            'oo-ui-panelLayout-padded',
            'oo-ui-panelLayout-framed'
        ]).append(
             $('<form>', {
             $('<form>', {
                 html: [
                 html: [
                     $('<p>', {
                     $optionsFieldset,
                        html: [
                     $actionsFieldset,
                            $('<label>', {
                                'for': 'microcode',
                                'text': 'Microcode:'
                            }),
                            $('<input>', {
                                change: updateFile,
                                name: 'microcode',
                                id: 'microcode',
                                type: 'file'
                            })
                        ]
                    }),
                    $('<p>', {
                        html: [
                            $('<label>', {
                                'for': 'configuration',
                                'text': 'Configuration:'
                            }),
                            $('<input>', {
                                change: updateFile,
                                name: 'configuration',
                                id: 'configuration',
                                type: 'file'
                            })
                        ]
                    }),
                    $('<p>', {
                        html: [
                            $('<label>', {
                                'for': 'diagram-generator-student-name',
                                'text': 'Student name:'
                            }),
                            $('<input>', {
                                name: 'diagram-generator-student-name',
                                id: 'diagram-generator-student-name',
                                placeholder: 'Pera Pisar',
                                type: 'text'
                            })
                        ]
                    }),
                    $('<p>', {
                        html: [
                            $('<label>', {
                                'for': 'diagram-generator-student-index',
                                'text': 'Student index:'
                            }),
                            $('<input>', {
                                name: 'diagram-generator-student-index',
                                id: 'diagram-generator-student-index',
                                placeholder: '2021/0000',
                                type: 'text'
                            })
                        ]
                     }),
                    $('<p>', {
                        html: [
                            $('<input>', {
                                id: 'diagram-generator-submit',
                                type: 'submit',
                                value: 'Generate'
                            }),
                            $('<label>', {
                                'for': 'diagram-generator-new-page',
                                'text': 'Generate on new page'
                            }),
                            $('<input>', {
                                id: 'diagram-generator-new-page',
                                name: 'diagram-generator-new-page',
                                type: 'checkbox'
                            })
                        ]
                    }),
                     $('<p>', {
                     $('<p>', {
                         id: 'diagram-generator-error'
                         id: 'diagram-generator-error'
                     })
                     })
                 ],
                 ]
                submit: generate
             }).addClass(['mw-htmlform', 'mw-htmlform-ooui', 'oo-ui-layout', 'oo-ui-formLayout']),
             }),
             $('<div>', {
             $('<div>', {
                 id: 'diagram-generator-result'
                 id: 'diagram-generator-result'
             })
             })
         );
         );
        if ($.fn.makeCollapsible) {
            $optionsFieldset.makeCollapsible();
            $actionsFieldset.makeCollapsible();
        }
         updateSubmitEnabled();
         updateSubmitEnabled();
     }
     }

Верзија на датум 4. фебруар 2023. у 04:59

(function() {
    'use strict';
    var lib = mw.libs.diagramGenerator;
    var fileContents = {};

    function updateSubmitEnabled() {
        if (fileContents.microcode && fileContents.configuration) {
            $('#diagram-generator-submit').removeAttr('disabled');
        } else {
            $('#diagram-generator-submit').attr('disabled', '');
        }
    }

    function fileLoaded(id) {
        fileContents[id] = this.result;
        updateSubmitEnabled();
    }

    function updateFile(event) {
        var input = event.target;
        delete fileContents[input.id];
        var files = input.files;
        if (files.length === 0) {
            return;
        }
        var reader = new FileReader();
        reader.addEventListener('load', fileLoaded.bind(reader, input.id));
        reader.readAsText(files[0]);
        updateSubmitEnabled();
    }

    function downloadSVG(svg) {
        var contents = [
            '<?xml version="1.0" encoding="utf-8"?>',
            '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">',
            svg.outerHTML
        ].join('\n');
        var blob = new Blob([contents], {
            type: 'image/svg+xml'
        });
        var blobUrl = URL.createObjectURL(blob);
        var downloadLink = document.createElement('a');
        downloadLink.href = blobUrl;
        downloadLink.download = 'Diagram.svg';
        document.body.appendChild(downloadLink);
        downloadLink.click();
        URL.revokeObjectURL(blobUrl);
        downloadLink.remove();
    }

    function printPages(width, height, pages) {
        var imageWindow = window.open('');
        pages.forEach(function(page) {
            var svg = lib.createSVG(width, height);
            svg.appendChild(page);
            svg.style.breakAfter = 'page';
            imageWindow.document.write(svg.outerHTML);
        });
        imageWindow.document.close();
        imageWindow.focus();
        imageWindow.print();
    }

    function postGeneration(parameters, actionId, pages) {
        switch (actionId) {
            case 'diagram-generator-this-page':
                var svg = lib.createSVGWithPages(parameters.width, parameters.height, pages);
                $('#diagram-generator-result').html(svg.outerHTML);
                break;
            case 'diagram-generator-new-page':
                printPages(parameters.width, parameters.height, pages);
                break;
            case 'diagram-generator-download-svg':
                downloadSVG(lib.createSVGWithPages(parameters.width, parameters.height, pages));
                break;
            default:
                // ???
                break;
        }
    }

    function getParameters() {
        return {
            arrowHeight: 15,
            columnHeaderLeft: 'Dijagram toka mikrooperacija',
            columnHeaderMiddle: 'Dijagram toka upravljačkih signala',
            columnHeaderRight: 'Sekvenca upravljačkih signala',
            headerHeight: 20,
            height: 1680,
            indexNum: $('#diagram-generator-student-index').val(),
            footerRowHeight: 50,
            margin: 50,
            nameSurname: $('#diagram-generator-student-name').val(),
            subjectName: 'Osnovi računarske tehnike 2',
            width: 1200
        };
    }

    function generate(event) {
        event.preventDefault();
        $('#diagram-generator-error').text('');
        var config = lib.parseConfig(fileContents.configuration);
        if (!config) {
            $('#diagram-generator-error').text('Error while parsing configuration.');
            return;
        }
        var instructionsResult = lib.getInstructions(config, fileContents.microcode);
        if (instructionsResult.error) {
            $('#diagram-generator-error').text(instructionsResult.error);
        }
        var instructions = instructionsResult.result;
        var parameters = getParameters();
        var pages = lib.getPages(parameters, config, instructions);
        postGeneration(parameters, event.currentTarget.id, pages);
    }

    function createFieldset(text, contents) {
        var $icon = $('<span>').addClass([
            'oo-ui-widget',
            'oo-ui-widget-enabled',
            'oo-ui-iconElement-icon',
            'oo-ui-iconElement',
            'oo-ui-labelElement-invisible',
            'oo-ui-iconWidget'
        ]);
        return $('<fieldset>', {
            html: [
                $('<legend>', {
                    html: [
                        $('<span>', {
                            'class': 'oo-ui-labelElement-label',
                            'text': text
                        }),
                        $icon.clone().addClass('oo-ui-icon-expand'),
                        $icon.clone().addClass('oo-ui-icon-collapse')
                    ],
                    role: 'button',
                    tabindex: 0
                }).addClass(['oo-ui-fieldsetLayout-header', 'mw-collapsible-toggle']),
                $('<div>', {
                    'class': 'oo-ui-fieldsetLayout-group',
                    'html': $('<div>', {
                        'class': 'oo-ui-widget oo-ui-widget-enabled',
                        'html': contents
                    })
                })
            ]
        }).addClass([
            'oo-ui-layout',
            'oo-ui-labelElement',
            'oo-ui-fieldsetLayout',
            'mw-collapsible',
            'mw-made-collapsible'
        ]);
    }

    function createFormRow(text, options) {
        var inputOptions = $.extend({}, options, {
            'class': 'oo-ui-inputWidget-input',
            'name': options.id
        });
        return $('<div>', {
            html: $('<div>', {
                'class': 'oo-ui-fieldLayout-body',
                'html': [
                    $('<span>', {
                        'class': 'oo-ui-fieldLayout-header',
                        'html': $('<label>', {
                            'class': 'oo-ui-labelElement-label',
                            'for': options.id,
                            'text': text + ':'
                        })
                    }),
                    $('<div>', {
                        'class': 'oo-ui-fieldLayout-field',
                        'html': $('<div>', {
                            html: $('<input>', inputOptions)
                        }).addClass([
                            'oo-ui-widget',
                            'oo-ui-widget-enabled',
                            'oo-ui-inputWidget',
                            'oo-ui-textInputWidget',
                            'oo-ui-textInputWidget-type-text'
                        ])
                    })
                ]
            })
        }).addClass([
            'mw-htmlform-field-HTMLTextField',
            'oo-ui-layout',
            'oo-ui-labelElement',
            'oo-ui-fieldLayout',
            'oo-ui-fieldLayout-align-top'
        ]);
    }

    function createFormButton(text, options) {
        return $('<span>', $.extend({
            'class': [
                'oo-ui-buttonElement',
                'oo-ui-buttonElement-framed',
                'oo-ui-flaggedElement-primary',
                'oo-ui-flaggedElement-progressive',
                'oo-ui-labelElement',
                'oo-ui-widget-enabled'
            ].join(' ')
        }, options)).append(
            $('<button>', {
                'class': 'oo-ui-buttonElement-button',
                'tabindex': '0'
            }).append(
                $('<span>', {
                    'class': 'oo-ui-labelElement-label label',
                    'text': text
                })
            )
        );
    }

    function init() {
        var $optionsFieldset = createFieldset('Options', [
            createFormRow('Microcode', {
                change: updateFile,
                id: 'microcode',
                type: 'file'
            }),
            createFormRow('Configuration', {
                change: updateFile,
                id: 'configuration',
                type: 'file'
            }),
            createFormRow('Student name', {
                id: 'diagram-generator-student-name',
                placeholder: 'Pera Pisar',
                type: 'text'
            }),
            createFormRow('Student index', {
                id: 'diagram-generator-student-index',
                placeholder: '2021/0000',
                type: 'text'
            })
        ]);
        var $actionsFieldset = createFieldset('Actions', [
            createFormButton('Generate (on page)', {
                click: generate,
                id: 'diagram-generator-this-page'
            }),
            createFormButton('Print (new page)', {
                click: generate,
                id: 'diagram-generator-new-page'
            }),
            createFormButton('Download SVG', {
                click: generate,
                id: 'diagram-generator-download-svg'
            })
        ]);
        $('#diagram-generator').addClass([
            'mw-htmlform-ooui-wrapper',
            'oo-ui-layout',
            'oo-ui-panelLayout',
            'oo-ui-panelLayout-padded',
            'oo-ui-panelLayout-framed'
        ]).append(
            $('<form>', {
                html: [
                    $optionsFieldset,
                    $actionsFieldset,
                    $('<p>', {
                        id: 'diagram-generator-error'
                    })
                ]
            }).addClass(['mw-htmlform', 'mw-htmlform-ooui', 'oo-ui-layout', 'oo-ui-formLayout']),
            $('<div>', {
                id: 'diagram-generator-result'
            })
        );
        if ($.fn.makeCollapsible) {
            $optionsFieldset.makeCollapsible();
            $actionsFieldset.makeCollapsible();
        }
        updateSubmitEnabled();
    }

    $(init);
})();