393 lines
9.9 KiB
HTML
393 lines
9.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>FSM Designer</title>
|
|
|
|
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,700" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css"
|
|
integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
|
|
<link href="lib/tingle/tingle.min.css" rel="stylesheet">
|
|
|
|
<style>
|
|
/**
|
|
* General
|
|
*/
|
|
|
|
html, body {
|
|
font-family: Roboto, Arial, sans-serif;
|
|
font-size: 16px;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
background: #eee;
|
|
}
|
|
|
|
.container {
|
|
max-width: 800px;
|
|
margin: 20px auto;
|
|
padding: 0 40px;
|
|
}
|
|
|
|
input:not([type=checkbox]) {
|
|
width: 100%;
|
|
font-size: 16px;
|
|
padding: 8px 16px;
|
|
border-radius: 10px;
|
|
border: none;
|
|
color: #333;
|
|
background-color: rgba(0, 0, 0, .1);
|
|
}
|
|
|
|
input:focus {
|
|
background-color: rgba(0, 0, 0, .2);
|
|
}
|
|
|
|
label {
|
|
display: block;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
/**
|
|
* Buttons
|
|
*/
|
|
|
|
.btn {
|
|
padding: 8px 16px;
|
|
border-radius: 10px;
|
|
border: 1px solid transparent;
|
|
background: none;
|
|
font-weight: bold;
|
|
font-family: Roboto, Arial, sans-serif;
|
|
}
|
|
|
|
.btn:hover {
|
|
border: 1px solid rgba(0, 0, 0, .33);
|
|
background: rgba(0, 0, 0, .15);
|
|
}
|
|
|
|
.btn:active {
|
|
box-shadow: 0 0 5px rgba(0, 0, 0, .25);
|
|
}
|
|
|
|
.btn-close {
|
|
padding: 4px 6px;
|
|
}
|
|
|
|
/**
|
|
* FSMDocument tabs
|
|
*/
|
|
|
|
.document-tabs-container {
|
|
overflow-x: auto;
|
|
}
|
|
|
|
#document-tabs {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
height: 44px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
#document-tabs .document-tab {
|
|
display: inline-block;
|
|
border: 1px solid rgba(0, 0, 0, .33);
|
|
margin: 0;
|
|
padding: 8px 16px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
#document-tabs .document-tab:first-child {
|
|
border-top-left-radius: 10px;
|
|
border-bottom-left-radius: 10px;
|
|
}
|
|
|
|
#document-tabs .document-tab:last-child {
|
|
border-top-right-radius: 10px;
|
|
border-bottom-right-radius: 10px;
|
|
}
|
|
|
|
#document-tabs .document-tab .document-name {
|
|
font-weight: normal;
|
|
margin-right: 4px;
|
|
}
|
|
|
|
#document-tabs .document-tab.active {
|
|
background: #fff;
|
|
}
|
|
|
|
#document-tabs .document-tab.active .document-name {
|
|
font-weight: bold;
|
|
}
|
|
|
|
/**
|
|
* Action Buttons
|
|
*/
|
|
|
|
.action-buttons {
|
|
margin: 20px 0;
|
|
}
|
|
|
|
.action-button {
|
|
background: #fff;
|
|
margin: 4px 8px;
|
|
}
|
|
|
|
.action-button .fa {
|
|
margin: 4px;
|
|
}
|
|
|
|
/**
|
|
* List in Open Modal
|
|
*/
|
|
|
|
.file-list {
|
|
list-style-type: none;
|
|
width: 100%;
|
|
padding: 0;
|
|
}
|
|
|
|
.file-list .file-list-item {
|
|
padding: 16px 32px;
|
|
border-bottom: 1px solid rgba(0, 0, 0, .33);
|
|
width: 100%;
|
|
}
|
|
|
|
.file-list .file-list-item:first-child {
|
|
border-top-left-radius: 10px;
|
|
border-top-right-radius: 10px;
|
|
}
|
|
|
|
.file-list .file-list-item:last-child {
|
|
border: none;
|
|
border-bottom-left-radius: 10px;
|
|
border-bottom-right-radius: 10px;
|
|
}
|
|
|
|
.file-list .file-list-item:hover {
|
|
background: rgba(0, 0, 0, .1);
|
|
}
|
|
|
|
.file-list .file-list-item:active {
|
|
background: rgba(0, 0, 0, .2);
|
|
}
|
|
|
|
/**
|
|
* Import Modal with Upload Button
|
|
*/
|
|
|
|
.upload-btn {
|
|
border: 1px solid rgba(0, 0, 0, .33);
|
|
background: #fff;
|
|
}
|
|
|
|
.upload-btn:hover {
|
|
background: rgba(0, 0, 0, .1);
|
|
}
|
|
|
|
.upload-btn:active {
|
|
background: rgba(0, 0, 0, .2);
|
|
}
|
|
|
|
.upload-btn .upload-input {
|
|
display: none;
|
|
}
|
|
|
|
/**
|
|
* Canvas
|
|
*/
|
|
|
|
#canvas {
|
|
display: block;
|
|
margin: 0 auto;
|
|
background: #fff;
|
|
border-radius: 10px;
|
|
width: calc(100% - 20px);
|
|
}
|
|
|
|
#previewImage {
|
|
width: 100%;
|
|
}
|
|
|
|
.explanation {
|
|
max-width: 800px;
|
|
margin: 10px auto;
|
|
padding: 0 20px;
|
|
}
|
|
|
|
/**
|
|
* Context Menu
|
|
*/
|
|
|
|
.contextmenu {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
display: none;
|
|
border-radius: 10px;
|
|
border: 1px solid rgba(0, 0, 0, .33);
|
|
box-shadow: 0 0 4px rgba(0, 0, 0, .15);
|
|
margin: 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
min-width: 150px;
|
|
background: #fff;
|
|
}
|
|
|
|
.contextmenu > li {
|
|
padding: 8px 16px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.contextmenu > li:first-child {
|
|
border-top-left-radius: 10px;
|
|
border-top-right-radius: 10px;
|
|
}
|
|
|
|
.contextmenu > li:last-child {
|
|
border-bottom-left-radius: 10px;
|
|
border-bottom-right-radius: 10px;
|
|
}
|
|
|
|
.contextmenu > li:hover {
|
|
background: rgba(0, 0, 0, .1);
|
|
}
|
|
|
|
.contextmenu > li:active {
|
|
background: rgba(0, 0, 0, .2);
|
|
}
|
|
|
|
/**
|
|
* Drag Overlay
|
|
*/
|
|
|
|
#dragOverlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, .75);
|
|
padding: 20px;
|
|
color: #fff;
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
-webkit-box-sizing: border-box;
|
|
-moz-box-sizing: border-box;
|
|
box-sizing: border-box;
|
|
-webkit-transition: opacity .25s;
|
|
-moz-transition: opacity .25s;
|
|
-ms-transition: opacity .25s;
|
|
-o-transition: opacity .25s;
|
|
transition: opacity .25s;
|
|
}
|
|
|
|
#dragOverlay.visible {
|
|
opacity: 1;
|
|
pointer-events: all;
|
|
cursor: pointer;
|
|
}
|
|
|
|
#dragOverlay .border {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 10px;
|
|
border: 4px dashed white;
|
|
-webkit-box-sizing: border-box;
|
|
-moz-box-sizing: border-box;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
#dragOverlay .content {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%);
|
|
text-align: center;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="container">
|
|
|
|
<nav class="document-tabs-container">
|
|
<ul id="document-tabs">
|
|
</ul>
|
|
</nav>
|
|
|
|
<div class="action-buttons">
|
|
|
|
<button class="btn action-button" id="addBtn"><i class="fa fa-plus"></i> Neu</button>
|
|
|
|
<button class="btn action-button" id="saveBtn"><i class="fa fa-save"></i> Speichern</button>
|
|
|
|
<button class="btn action-button" id="openBtn"><i class="fa fa-folder-open"></i> Öffnen</button>
|
|
|
|
<button class="btn action-button" id="importBtn"><i class="fa fa-file-import"></i> Importieren</button>
|
|
|
|
<button class="btn action-button" id="exportBtn"><i class="fa fa-file-export"></i> Exportieren</button>
|
|
|
|
<button class="btn action-button" id="simulateBtn"><i class="fa fa-play"></i> Simulieren</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<canvas id="canvas"></canvas>
|
|
|
|
<div class="explanation">
|
|
|
|
<p>Oben befindet sich der sogenannter FSM-Designer. Dieser ermöglicht es unter anderem deterministische endliche Automaten zu erstellen.</p>
|
|
|
|
<p>Funktionsweise:</p>
|
|
|
|
<ul>
|
|
<li><b>Zustand hinzufügen:</b> Doppelklick</li>
|
|
<li><b>Übergang hinzufügen:</b> <code>Shift</code> gedrückt halten und mit linker Maustaste ziehen</li>
|
|
<li><b>Verschieben:</b> klassisches Drag'n'drop</li>
|
|
<li><b>Endzustand:</b> Doppelklick auf einen bestehenden Zustand</li>
|
|
<li><b>Index:</b> Unterstrich vor eine Zahl hinzufügen (z.B. <code>q_0</code>)</li>
|
|
<li><b>Griechischer Buchstabe:</b> Name des Buchstaben mit Backslash (z.B. <code>\epsilon</code>)</li>
|
|
</ul>
|
|
|
|
<p>Diese Anwendung wurde mithilfe von HTML5 Canvas und JavaScript ECMA2016 erstellt.</p>
|
|
|
|
<p>Der Source Code ist open source auf <a href="https://git.kingofdog.eu/KingOfDog/fsm-designer">Gitea</a> verfügbar (demnächst womöglich auch über Github).</p>
|
|
|
|
<p>Made with <i class="fa fa-heart"></i> by <a href="https://kingofdog.eu">KingOfDog</a>.</p>
|
|
|
|
</div>
|
|
|
|
<ul id="contextmenuCanvas" class="contextmenu">
|
|
<li>Test</li>
|
|
</ul>
|
|
|
|
<div id="dragOverlay">
|
|
<div class="border"></div>
|
|
<div class="content">
|
|
<h1>Datei ablegen (.fsm)</h1>
|
|
<h3>Dokument importieren und weiterarbeiten!</h3>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="lib/tingle/tingle.min.js"></script>
|
|
<script src="lib/contextmenu.js/contextMenu.min.js"></script>
|
|
|
|
<script src="js/math.js"></script>
|
|
<script src="js/export/export.js"></script>
|
|
<script src="js/export/export-image.js"></script>
|
|
<script src="js/components/connection.js"></script>
|
|
<script src="js/components/start-connection.js"></script>
|
|
<script src="js/components/self-connection.js"></script>
|
|
<script src="js/components/temporary-connection.js"></script>
|
|
<script src="js/components/state.js"></script>
|
|
<script src="js/fsm-document.js"></script>
|
|
<script src="js/main.js"></script>
|
|
<script src="js/simulate.js"></script>
|
|
<script src="js/menu.js"></script>
|
|
</body>
|
|
</html>
|