Replaces & merges MiRCART-{nw,python,www} w/ original MiRCART as of Thu Jul 5 2018.

This commit is contained in:
Lucio Andrés Illanes Albornoz 2019-09-01 16:34:00 +02:00
parent 08b453b33f
commit cf2c5a7042
103 changed files with 1834 additions and 10148 deletions

2
.gitattributes vendored
View File

@ -1,2 +0,0 @@
MiRCART-cordoba/* linguist-vendored
MiRCART-nw/* linguist-vendored

9
.gitignore vendored
View File

@ -1,8 +1,3 @@
*.sw[op]
MiRCART-cordoba/node_modules
MiRCART-cordoba/platforms/android/.gradle
MiRCART-cordoba/platforms/android/app/build
MiRCART-cordoba/platforms/android/CordovaLib/build
MiRCART-cordoba/releases/*
MiRCART-nw/releases/*
MiRCART-www/releases/*
__pycache__/
MiRCARTImgurApiKey.py

View File

@ -1 +0,0 @@
../assets/text/LICENCE.asdf

View File

@ -1,3 +0,0 @@
@echo off
start nw.exe .
rem vim:fileformat=dos

View File

@ -1 +0,0 @@
../assets

View File

@ -1 +0,0 @@
../assets/shell/deploy-nw.sh

View File

@ -1 +0,0 @@
../assets/html/index.html

View File

@ -1,4 +0,0 @@
a9e66b292c80e86f51b616933e8491dad4007da1abe4a0ee85a3477edfd2750f releases/nwjs-v0.34.5-linux-ia32.tar.gz
2d50bc19619e9a26ace46da3a4f3a4a0e9850920267300eb35759df4cb92e2b5 releases/nwjs-v0.34.5-linux-x64.tar.gz
10409d5519662f25c1a97b027492da13cc42c8cc464c08b76de945969ae33413 releases/nwjs-v0.34.5-win-ia32.zip
77138f6965ad1ae6eba3390e5c6403d3156431ac5247fac39f4491a7c625a216 releases/nwjs-v0.34.5-win-x64.zip

View File

@ -1,5 +0,0 @@
{
"name": "MiRCART",
"version": "1.1.6",
"lockfileVersion": 1
}

View File

@ -1,31 +0,0 @@
{
"author": "Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>, based on work by JOLLO NET NA",
"bugs": {
"url": "https://github.com/lalbornoz/MiRCART/issues"
},
"description": "MiRCART (standalone NW app)",
"directories": {
"assets": "assets"
},
"homepage": "https://github.com/lalbornoz/MiRCART#readme",
"license": "Jollo LNT license <https://raw.githubusercontent.com/lalbornoz/MiRCART/master/LICENCE>",
"main": "index.html",
"name": "MiRCART-nw",
"repository": {
"type": "git",
"url": "git+https://github.com/lalbornoz/MiRCART.git"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"version": "1.1.6",
"window": {
"title": "MiRCART (standalone NW app)",
"toolbar": true,
"position": "center",
"width": 1024,
"height": 768,
"min_width": 1024,
"min_height": 768
}
}

View File

@ -1,3 +0,0 @@
MiRCARTImgurApiKey.py
__pycache__/
*.sw[op]

View File

@ -1 +0,0 @@
../assets/text/LICENCE.MIT

View File

@ -1 +0,0 @@
../assets/text/LICENCE.asdf

View File

@ -1 +0,0 @@
../assets

View File

@ -1 +0,0 @@
../assets/shell/deploy-www.sh

View File

@ -1 +0,0 @@
../assets/html/index.html

31
MiRCART.py Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env python3
#
# MiRCART.py -- mIRC art editor for Windows & Linux
# Copyright (c) 2018, 2019 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
import os, sys
sys.path.append(os.path.join(os.getcwd(), "libcanvas"))
sys.path.append(os.path.join(os.getcwd(), "libgui"))
sys.path.append(os.path.join(os.getcwd(), "librtl"))
sys.path.append(os.path.join(os.getcwd(), "libtools"))
from MiRCARTFrame import MiRCARTFrame
import wx
#
# Entry point
def main(*argv):
wxApp = wx.App(False)
appFrame = MiRCARTFrame(None)
if len(argv) > 1 \
and len(argv[1]) > 0:
appFrame.panelCanvas.canvasInterface.canvasPathName = argv[1]
appFrame.panelCanvas.canvasImportStore.importTextFile(argv[1])
appFrame.panelCanvas.canvasImportStore.importIntoPanel()
appFrame.onCanvasUpdate(pathName=argv[1], undoLevel=-1)
wxApp.MainLoop()
if __name__ == "__main__":
main(*sys.argv)
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -1,43 +0,0 @@
/*
* Background mIRC colours
*/
.ba {background-color: #FFFFFF}
.bb {background-color: #000000}
.bc {background-color: #00007F}
.bd {background-color: #009300}
.be {background-color: #FF0000}
.bf {background-color: #7f0000}
.bg {background-color: #9C009C}
.bh {background-color: #FC7F00}
.bi {background-color: #FFFF00}
.bj {background-color: #00FC00}
.bk {background-color: #009393}
.bl {background-color: #00FFFF}
.bm {background-color: #0000FC}
.bn {background-color: #FF00FF}
.bo {background-color: #7F7F7F}
.bp {background-color: #D2D2D2}
/*
* Foreground mIRC colours
*/
.fa {color: #FFFFFF}
.fb {color: #000000}
.fc {color: #00007F}
.fd {color: #009300}
.fe {color: #FF0000}
.ff {color: #7F0000}
.fg {color: #9C009C}
.fh {color: #FC7F00}
.fi {color: #FFFF00}
.fj {color: #00FC00}
.fk {color: #009393}
.fl {color: #00FFFF}
.fm {color: #0000FC}
.fn {color: #FF00FF}
.fo {color: #7F7F7F}
.fp {color: #D2D2D2}
/*
* vim:ts=2 sw=2 expandtab fenc=utf-8 foldmethod=marker nowrap tw=0
*/

View File

@ -1,13 +0,0 @@
@font-face {
font-family: 'FixedsysExcelsior301Regular';
font-style: normal;
src: url('../fonts/fsex300-webfont.eot');
src: url('../fonts/fsex300-webfont.eot?#iefix') format('embedded-opentype'),
url('../fonts/fsex300-webfont.woff') format('woff'),
url('../fonts/fsex300-webfont.ttf') format('truetype'),
url('../fonts/fsex300-webfont.svg#FixedsysExcelsior301Regular') format('svg');
}
/*
* vim:ts=2 sw=2 expandtab fenc=utf-8 foldmethod=marker nowrap tw=0
*/

View File

@ -1,48 +0,0 @@
body {
background: #000000;
background-image: url('../images/tile.jpg');
color: rgb(255,255,0);
font-family: times new roman;
font-family: 'FixedsysExcelsior301Regular';
font-size: 16pt;
}
/* {{{ DIV id styles */
div#box {
background: rgba(0,0,100,0.5);
border: 3px solid #0000ff;
border-spacing: 0px;
color: #00ffff!important;
display: inline-block;
font-size: 20px;
font-size: 12pt!important;
margin: 10px 0;
padding: 10px;
}
div#box_wrapper {
margin: 0 auto;
width: 50%;
}
/* }}} */
/* {{{ Element styles */
h1 {
color: #ff00ff!important;
font-size: 42px;
margin-bottom: 15px;
}
h2 {
color: #00ffff!important;
margin-bottom: 15px;
margin-top: 15px;
}
p {
color: white;
}
pre {
color: white;
}
/* }}} */
/*
* vim:ts=2 sw=2 expandtab fenc=utf-8 foldmethod=marker nowrap tw=0
*/

View File

@ -1,302 +0,0 @@
/* {{{ BODY.grid styles */
body.grid div {
border-left: 1px solid #444444;
}
body.grid span {
border-bottom: 1px solid #444444;
border-right: 1px solid #444444;
}
body.grid .tool {
border: 1px solid #444444;
}
body.grid #brush_wrapper > div:first-child,
body.grid #canvas_wrapper > div:first-child,
body.grid #letters_wrapper > div:first-child,
body.grid #palette_wrapper > div:first-child {
border-top: 1px solid #444444;
}
/* }}} */
/* {{{ .initial styles */
.initial #add_custom_el,
.initial #doc_el,
.initial #export_format_el,
.initial #export_textarea,
.initial #import_button,
.initial #import_format_el,
.initial #import_textarea,
.initial #grid_el,
.initial #load_el,
.initial #save_el,
.initial #vertical_checkbox {
}
/* }}} */
/* {{{ .selector_el styles */
.selector_el {
border: 1px dashed white !important;
left: -999px;
margin-top: -1px;
padding-top: 1px;
pointer-events: none;
position: absolute;
top: -999px;
}
.selector_el.creating div {
display: none; }
.selector_el.dragging {
color: #00FF00;
}
/* }}} */
/* {{{ .tool styles */
.tool {
cursor: pointer;
}
.tool.focused {
color: white;
text-decoration: underline;
}
.tool.locked.focused {
box-shadow: 0 0;
}
.tool.radio {
margin: 0 8px 0 0;
}
.tool.radio.focused {
background-color: #6D6D6D;
box-shadow: none;
color: black;
}
/* }}} */
/* {{{ .vertical styles */
.vertical .wrapper, .vertical .block {
float: left;
}
.vertical #brush_container {
display: inline-block;
float: left;
}
.vertical #canvas_wrapper,
.vertical #canvas_wrapper div,
.vertical #palette_wrapper,
.vertical #palette_wrapper {
margin-right: 10px;
}
.vertical #secret_wrapper {
margin-right: 10px;
}
.vertical #secret_wrapper span {
clear: both;
float: left;
}
.vertical #tools_block {
min-width: 100%;
}
.vertical #tools_wrapper,
.vertical #ui_wrapper {
clear: none;
float: left;
width: 320px;
}
.vertical #workspace_wrapper {
float: left;
position: relative;
width: auto;
}
/* }}} */
/* {{{ Class & id styles (simple) */
.bucket #canvas_wrapper { cursor: url(../images/bucket.png) 3 15, auto; }
.dropper #canvas_wrapper { cursor: url(../images/dropper.gif) 0 15, auto; }
.faded { color: #404040; }
.hidden { visibility: hidden; }
.loading .vertical #ui_wrapper { clear: none }
#experimental_palette_toggle.focused { box-shadow: none; }
#export_wrapper { display: none; }
#import_wrapper { display: none; }
#tools_block > * { cursor: crosshair; }
#workspace_wrapper { width: 100%; }
/* }}} */
/* {{{ Class styles (complex) */
.ba.focused {
box-shadow: inset 0 0px 2px #000, inset 0 0px 2px black;
border-color: black;
}
.block {
background-color: black;
float: left;
height: auto;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
width: auto;
}
.block {
padding: 4px;
}
.block:nth-child(n+2) {
padding-left: 30px;
}
.close {
background: black;
cursor: pointer;
padding: 10px;
position: absolute;
right: 20px;
top: 20px;
z-index: 2;
}
.custom {
float: left;
margin-bottom: 5px;
margin-right: 5px;
}
.ed {
color: white;
}
.ed.focused {
color: white;
text-decoration: underline;
}
.faba.focused, .fbba.focused, .fcba.focused, .fdba.focused, .feba.focused, .ffba.focused, .fgba.focused, .fhba.focused,
.fiba.focused, .fjba.focused, .fkba.focused, .flba.focused, .fmba.focused, .fnba.focused, .foba.focused, .fpba.focused {
box-shadow: inset 1px 0 2px #888888, inset -1px 0 2px #888888, inset 0 1px 2px #888888, inset 0 -1px 2px #888888;
}
.focused {
box-shadow: inset 1px 0 2px white, inset -1px 0 2px white, inset 0 1px 2px white, inset 0 -1px 2px white;
border-color: white;
}
.locked {
border-bottom: 1px solid;
color: #bbbbbb;
text-decoration: none;
}
.transparent {
background-color: transparent;
background-image: url(../images/gray-dither.gif);
background-size: 8px 8px;
}
@media (-webkit-min-device-pixel-ratio: 2) {
.transparent {
background-size: 4px 4px;
}
}
.wrapper {
background-color: black;
cursor: crosshair;
float: left;
height: auto;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
white-space: pre-wrap;
width: auto;
word-wrap: break-word;
}
/* }}} */
/* {{{ Element styles */
a {
display: block;
}
a:link, a:visited {
color: #6B6760;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
body {
background-color: black !important;
transition: 0.1s linear;
}
body.loading {
opacity: 0;
}
span {
display: inline-block;
line-height: 15px;
min-width: 8px;
}
textarea, input[type=text], body {
color: #6D6B6D;
font-family: 'FixedsysExcelsior301Regular';
-webkit-font-smoothing: antialiased !important;
line-height: 11pt;
font-size: 12pt;
font-weight: 100;
margin: 0;
}
/* }}} */
/* {{{ Id styles (complex) */
#brush_wrapper {
border: 1px solid;
display: inline-block;
float: left;
margin-bottom: 13px;
padding-right: 10px;
}
#brush_wrapper, #letters_wrapper {
cursor: crosshair;
}
#canvas_wrapper {
box-shadow: 0 0 2px rgba(255,255,255,0.3);
margin: 3px;
white-space: pre;
}
#cursor_input {
font-size: 16px;
opacity: 0;
position: fixed;
right: 0;
top: 0;
width: 30px;
}
#export_textarea {
background: #001100;
border: 1px solid #333333;
color: #00FF00;
font-family: 'FixedsysExcelsior301Regular';
font-size: 12pt;
height: 300px;
outline: 0;
width: 37vw;
}
#import_textarea {
background: #001100;
border: 1px solid #333333;
color: #00FF00;
font-family: 'FixedsysExcelsior301Regular';
font-size: 12pt;
height: 300px;
outline: 0;
width: 37vw;
}
#letters_wrapper {
display: inline-block;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
}
#secret_wrapper {
clear: right;
float: left;
}
#secret_wrapper span {
float: left;
}
#textarea_mode {
float: left;
padding: 4px;
}
#ui_wrapper {
clear: both;
float: left;
width: 100vw;
}
#ui_wrapper .block {
width: 100px;
}
/* }}} */
/*
* vim:ts=2 sw=2 expandtab fenc=utf-8 foldmethod=marker nowrap tw=0
*/

Binary file not shown.

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Binary file not shown.

View File

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<!-- {{{ HEAD -->
<head>
<link charset="utf-8" href="../css/fonts.css" rel="stylesheet" type="text/css" />
<link charset="utf-8" href="../css/help.css" rel="stylesheet" type="text/css" />
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>MiRCART v1.1.6 documentation</title>
</head>
<!-- }}} -->
<!-- {{{ BODY -->
<body>
<div id="box_wrapper">
<div id="box">
<h1>MiRCART documentation</h1>
<h2>Tips on using the keyboard</h2>
<pre>
[ Decrease brush size
] Increase brush size
&lt;Alt&gt; + &lt;LMB&gt; on canvas Fill brush with sampled color
&lt;Alt&gt; + &lt;Shift&gt; + &lt;LMB&gt; on canvas Copy canvas to brush
&lt;Ctrl&gt; + &lt;LMB&gt; on brush Erase brush cell
&lt;Ctrl&gt; + &lt;LMB&gt; on canvas Draw with background color
&lt;Shift&gt; + &lt;LMB&gt; on canvas Draw line from last position
&lt;Shift&gt; + &lt;LMB&gt; on character box Switch to next character set
&lt;Shift&gt; + &lt;LMB&gt; on stored brush Delete stored brush
&lt;LMB&gt; on brush Fill brush cell
&lt;RMB&gt; on brush Erase brush cell
&lt;RMB&gt; on palette Set background color (when drawing with a letter)
</pre>
<h2>Notate bene</h2>
<p>
Characters not forming part of the initial set in the character box beneath the colour palette
encode to, assuming UTF-8, 2-3 bytes in total vs. one (1) byte for those part of the initial
set (e.g. 0-9, A-Z, a-z, etc.)<br />
<br />
Internet Explorer is explicitly unsupported.<br />
<br />
Repeating patterns of alternating back- and foreground colours, and vice versa, are encoded
using a single (1) byte in mIRC format (video reverse) and as such save space, especially
with large numbers of repetitions or alternations.
</p>
</div>
</div>
</body>
<!-- }}} -->
</html>
<!--
vim:ts=2 sw=2 expandtab fenc=utf-8 foldmethod=marker nowrap tw=0
-->

View File

@ -1,120 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<!-- {{{ HEAD -->
<head>
<link charset="utf-8" href="../css/ak.css" rel="stylesheet" type="text/css" />
<link charset="utf-8" href="../css/fonts.css" rel="stylesheet" type="text/css" />
<link charset="utf-8" href="../css/sally.css" rel="stylesheet" type="text/css" />
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<meta content="width=device-width, maximum-scale=1.0, user-scalable=yes" name="viewport" />
<title>MiRCART v1.1.6</title>
</head>
<!-- }}} -->
<!-- {{{ BODY -->
<body class="loading initial">
<!-- {{{ DIV: workspace_wrapper -->
<div id="workspace_wrapper">
<div id="canvas_wrapper" class="wrapper"></div>
</div>
<!-- }}} -->
<!-- {{{ DIV: ui_wrapper -->
<div id="ui_wrapper">
<!-- {{{ DIV: tools_block -->
<div class="block" id="tools_block">
<div id="palette_wrapper"></div>
<div id="secret_wrapper">
<span id="experimental_palette_toggle">.</span>
</div>
<div id="letters_wrapper"></div>
<div id="custom_wrapper"></div>
</div>
<!-- }}} -->
<!-- {{{ DIV: brush_container -->
<div id="brush_container" class="block">
<div id="brush_wrapper"></div>
<br />
<span id="fg_checkbox" class="tool">x fg</span><br />
<span id="bg_checkbox" class="tool">x bg</span><br />
<span id="char_checkbox" class="tool">x char</span><br />
<span id="add_custom_el" class="tool">+ add</span><br />
<br />
<span id="undo_el" class="tool hidden">undo</span><br />
<span id="redo_el" class="tool hidden">redo</span><br />
</div>
<!-- }}} -->
<!-- {{{ DIV: tools_wrapper -->
<div id="tools_wrapper" class="block">
<span id="square_el" class="tool">square</span><br />
<span id="circle_el" class="tool">circle</span><br />
<span id="cross_el" class="tool">cross</span><br />
<span id="text_el" class="tool">text</span><br />
<span id="fill_el" class="tool">fill</span><br />
<span id="select_el" class="tool">select</span><br />
<br />
<span id="rotate_el" class="tool">rotate</span><br />
<span id="scale_el" class="tool">scale</span><br />
<span id="translate_el" class="tool">translate</span><br />
<span id="slice_el" class="tool">slice</span><br />
</div>
<!-- }}} -->
<!-- {{{ DIV: textarea_mode -->
<div id="textarea_mode">
<div>
<span id="clear_el" class="tool">new</span>
<span id="save_el" class="tool">save</span>
<span id="load_el" class="tool">load</span>
<a id="doc_el" href="../html/help.html" target="_blank">help</a>
<br />
brush: <span id="brush_w_el" class="ed">5</span> x <span id="brush_h_el" class="ed">5</span><br />
canvas: <span id="canvas_w_el" class="ed">100</span> x <span id="canvas_h_el" class="ed">30</span><br />
<span id="grid_el" class="tool">_ grid</span>
<span id="vertical_checkbox" class="tool">x vertical</span>
</div>
<div id="export_wrapper">
<span id="export_format_el">ascii ansi *mirc</span>
<div id="gallery_wrapper"></div><br />
<div id="export_cutoff_warning_el">character limit of 425 exceeded</div>
<textarea id="export_textarea" cols="100" rows="30"></textarea>
</div>
<div id="import_wrapper">
<span id="import_format_el">ansi *mirc</span>
<span id="import_buttons">
<button id="import_button">import</button>
</span><br />
<textarea id="import_textarea" cols="100" rows="30"></textarea>
</div>
</div>
<input type="text" id="cursor_input" />
</div>
<!-- }}} -->
<!-- }}} -->
<!-- {{{ SCRIPTs: ../js/* -->
<script src="../js/util.js" type="text/javascript"></script>
<script src="../js/unicode.js" type="text/javascript"></script>
<script src="../js/color.js" type="text/javascript"></script>
<script src="../js/clipboard.js" type="text/javascript"></script>
<script src="../js/lex.js" type="text/javascript"></script>
<script src="../js/matrix.js" type="text/javascript"></script>
<script src="../js/gfx.js" type="text/javascript"></script>
<script src="../js/ui/tool.js" type="text/javascript"></script>
<script src="../js/gfx.js" type="text/javascript"></script>
<!-- }}} -->
<!-- {{{ SCRIPTs: ../js/ui/* -->
<script src="../js/ui/brush.js" type="text/javascript"></script>
<script src="../js/ui/canvas.js" type="text/javascript"></script>
<script src="../js/ui/keys.js" type="text/javascript"></script>
<script src="../js/ui/controls.js" type="text/javascript"></script>
<script src="../js/ui/paletters.js" type="text/javascript"></script>
<script src="../js/ui/selection.js" type="text/javascript"></script>
<script src="../js/ui/transform.js" type="text/javascript"></script>
<!-- }}} -->
<script src="../js/app.js" type="text/javascript"></script>
</body>
<!-- }}} -->
</html>
<!--
vim:ts=2 sw=2 expandtab fenc=utf-8 foldmethod=marker nowrap tw=0
-->

BIN
assets/images/MiRCART.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

BIN
assets/images/toolClone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

BIN
assets/images/toolFill.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

BIN
assets/images/toolLine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

BIN
assets/images/toolMove.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

BIN
assets/images/toolRect.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

BIN
assets/images/toolText.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

View File

@ -1,89 +0,0 @@
var dragging = false
var drawing = false
var erasing = false
var selecting = false
var filling = false
var changed = false
var transforming = false
var focused
var canvas, tools, palette, controls, brush, mode
var current_tool, current_filetool, current_canvas
var mouse = { x: 0, y: 0 }
function init () {
build()
bind()
}
function build () {
canvas.append(canvas_wrapper)
brush.append(brush_wrapper)
palette.append(palette_wrapper)
letters.append(letters_wrapper)
letters.repaint("Basic Latin")
controls.circle.focus()
brush.bg = colors.red
brush.generate()
brush.build()
// controls.grid.use()
canvas.resize_wrapper()
}
function bind () {
canvas.bind()
palette.bind()
letters.bind()
brush.bind()
controls.bind()
keys.bind()
clipboard.bind()
window.addEventListener('mouseup', function(e){
dragging = erasing = false
var ae = document.activeElement
if ((ae !== export_textarea) && (ae !== import_textarea)) {
cursor_input.focus()
}
if (selecting) {
selection.up(e)
}
else if (transforming) {
transform.up(e)
}
})
window.addEventListener("touchend", function(){
if (current_tool.name === "text") {
cursor_input.focus()
}
dragging = false
})
window.addEventListener('mousedown', function(e){
// cursor_input.focus()
})
document.addEventListener('DOMContentLoaded', function(){
cursor_input.focus()
document.body.classList.remove('loading')
})
window.onbeforeunload = function() {
// if (changed && !in_iframe()) return "You have edited this drawing."
}
function in_iframe () {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
}
init()

View File

@ -1,297 +0,0 @@
var clipboard = (function () {
var exports = {
format: "mirc",
exporting: false,
visible: false,
canvas: document.createElement("canvas"),
canvas_r: document.createElement("canvas"),
bind: function () {
export_textarea.addEventListener("focus", exports.export_focus)
export_textarea.addEventListener("blur", exports.blur)
import_button.addEventListener("click", exports.import_click)
import_textarea.addEventListener("focus", exports.import_focus)
import_textarea.addEventListener("paste", exports.paste)
},
setFormat: function (name) {
return function () {
clipboard.format = name
if (! clipboard.exporting) { clipboard.export_data() }
}
},
import_hide: function () { import_wrapper.style.display = "none"; clipboard.visible = false },
import_show: function () { import_wrapper.style.display = "block"; clipboard.visible = true; },
export_hide: function () { export_wrapper.style.display = "none"; clipboard.visible = false },
export_show: function () { export_wrapper.style.display = "block"; clipboard.visible = true; changed = false },
export_focus: function () {
if (! clipboard.exporting) {
export_textarea.focus()
export_textarea.select()
}
},
import_focus: function () {
import_textarea.focus()
import_textarea.select()
},
blur: function () {
},
export_mode: function () {
exports.export_focus()
clipboard.exporting = true
export_cutoff_warning_el.style.display = "none"
export_format_el.style.display = "inline"
clipboard.export_data()
},
import_mode: function () {
import_button.style.display = "inline"
import_format_el.style.display = "inline"
import_textarea.value = ""
exports.import_focus()
},
paste: function (e) {
e.preventDefault()
// images will come through as files
var types = toArray(e.clipboardData.types)
import_textarea.value = ""
types.forEach(function(type, i){
console.log(type)
// this can be text/plain or text/html..
if (type.match('text/plain')) {
import_textarea.value = e.clipboardData.getData(type)
}
else {
console.error("unknown type!", item.type)
}
})
},
import_click: function (data, no_undo) {
switch (controls.load_format.value) {
case 'ansi':
exports.import_ansi(data, no_undo)
break
case 'mirc':
exports.import_mirc(data, no_undo)
break
}
},
import_ansi: function (data, no_undo) {
if (data && data.preventDefault) {
data = import_textarea.value
} else {
data = data || import_textarea.value
}
var to_json = function(string, opts){
var lines_in = string.split(/\r?\n/)
var lines_out = []
var bg = 1, bg_ansi = 30, bold = false, fg = 15, fg_ansi = 37
var w = 0, h = 0
for (var y = 0; y < lines_in.length; y++) {
var cells = [], line = lines_in[y]
if (line.length === 0) {
continue
} else {
for (var x = 0; x < line.length; x++) {
var m = line.substring(x).match(/^\x1b\[((?:\d{1,3};?)+)m/)
if (m !== null) {
m[1].split(";").forEach(function(c){
c = parseInt(c);
if (c == 0) {
bg = 1; bg_ansi = 30; bold = false; fg = 15; fg_ansi = 37;
} else if (c == 1) {
bold = true; fg = ansi_fg_bold_import[fg_ansi];
} else if (c == 2) {
bold = false; fg = ansi_fg_import[fg_ansi];
} else if (ansi_bg_import[c] !== undefined) {
bg = ansi_bg_import[c]; bg_ansi = c;
} else if (bold && (ansi_fg_bold_import[c] !== undefined)) {
fg = ansi_fg_bold_import[c]; fg_ansi = c;
} else if (!bold && (ansi_fg_import[c] !== undefined)) {
fg = ansi_fg_import[c]; fg_ansi = c;
}
});
x += (m[0].length - 1);
} else {
m = line.substring(x).match(/^\x1b\[(\d+)C/)
if (m !== null) {
for (var n = 0, nmax = parseInt(m[1]); n < nmax; n++) {
cells.push({bg: bg, fg: fg, value: " "})
}
x += (m[0].length - 1);
} else {
cells.push({bg: bg, fg: fg, value: line[x]})
}
}
}
if (cells.length > 0) {
if (w < cells.length) {
w = cells.length
} else if (w > cells.length) {
for (var n = cells.length, nmax = w; n < nmax; n++) {
cells.push({bg: bg, fg: fg, value: " "})
}
}
lines_out.push(cells); h++;
}
}
}
return {h: h, lines: lines_out, w: w}
}
var json = to_json(data, {fg:0, bg:1})
if (!no_undo) undo.new()
if (!no_undo) undo.save_rect(0,0, canvas.w, canvas.h)
if (json.w !== canvas.w || json.h !== canvas.h){
if (!no_undo) undo.save_size(canvas.w, canvas.h)
canvas.resize(json.w, json.h, true)
}
canvas.clear()
for (var y = 0, line; line = json.lines[y]; y++){
var row = canvas.aa[y]
for (var x = 0, char; char = line[x]; x++){
var lex = row[x]
lex.char = char.value
lex.fg = char.fg
lex.bg = char.bg
lex.opacity = 1
lex.build()
}
}
current_filetool && current_filetool.blur()
},
import_mirc: function (data, no_undo) {
if (data && data.preventDefault) {
data = import_textarea.value
} else {
data = data || import_textarea.value
}
var to_json = function(string, opts){
var lines_in = string.split(/\r?\n/)
var lines_out = []
var w = 0, h = 0
for (var y = 0; y < lines_in.length; y++) {
var bg = 1, fg = 15
var cells = [], line = lines_in[y]
if (line.length === 0) {
continue
} else {
for (var x = 0; x < line.length; x++) {
switch (line[x]) {
case "\x02": // ^B (unimplemented)
break
case "\x03": // ^C
var parseColour = function(line, x) {
if (/1[0-5]/.test(line.substr(x, 2))) {
colour = parseInt(line.substr(x, 2))
return [colour, x + 2]
} else if (/0[0-9]/.test(line.substr(x, 2))) {
colour = parseInt(line.substr(x, 2))
return [colour, x + 2]
} else if (/[0-9]/.test(line.substr(x, 1))) {
colour = parseInt(line.substr(x, 1))
return [colour, x + 1]
} else {
return [undefined, x]
}
}
var bg_ = undefined, fg_ = undefined, x_ = x + 1;
[fg_, x_] = parseColour(line, x_)
if (line[x_] === ",") {
[bg_, x_] = parseColour(line, x_ + 1)
}
if ((bg_ == undefined) && (fg_ == undefined)) {
[bg, fg] = [1, 15]
} else {
bg = (bg_ != undefined) ? bg_ : bg;
fg = (fg_ != undefined) ? fg_ : fg;
};
if (x_ != x) {x = x_ - 1}; break;
case "\x06": // ^F (unimplemented)
break
case "\x0f": // ^O
[bg, fg] = [1, 15]; break;
case "\x16": // ^V
[bg, fg] = [fg, bg]; break;
case "\x1f": // ^_ (unimplemented)
break
default:
cells.push({bg: bg, fg: fg, value: line[x]})
}
}
if (cells.length > 0) {
if (w < cells.length) {
w = cells.length
}
lines_out.push(cells); h++;
}
}
}
return {h: h, lines: lines_out, w: w}
}
var json = to_json(data, {fg:0, bg:1})
if (!no_undo) undo.new()
if (!no_undo) undo.save_rect(0,0, canvas.w, canvas.h)
if (json.w !== canvas.w || json.h !== canvas.h){
if (!no_undo) undo.save_size(canvas.w, canvas.h)
canvas.resize(json.w, json.h, true)
}
canvas.clear()
for (var y = 0, line; line = json.lines[y]; y++){
var row = canvas.aa[y]
for (var x = 0, char; char = line[x]; x++){
var lex = row[x]
lex.char = char.value
lex.fg = char.fg
lex.bg = char.bg
lex.opacity = 1
lex.build()
}
}
current_filetool && current_filetool.blur()
},
export_data: function () {
var output
// switch (clipboard.format) {
switch (controls.save_format.value) {
case 'ascii':
output = canvas.ascii()
break
case 'ansi':
output = canvas.ansi()
break
case 'mirc':
output = canvas.mirc({cutoff: 425})
break
}
if (output.cutoff){
export_cutoff_warning_el.style.display = 'block'
} else {
export_cutoff_warning_el.style.display = 'none'
}
export_textarea.value = output
clipboard.export_focus()
return output
},
}
return exports
})()

View File

@ -1,163 +0,0 @@
var fillColor = 1 // black
var color_names = ("white black dark-blue green red dark-red purple orange " +
"yellow lime teal cyan blue magenta dark-gray light-gray").split(" ");
var all_color_hue_order = "dark-red red orange yellow lime green teal cyan blue dark-blue purple magenta black dark-gray light-gray white".split(" ");
var all_color_inv_order = "cyan teal blue dark-blue purple magenta dark-red red orange yellow lime green white light-gray dark-gray black".split(" ");
var color_hue_order = "dark-red red orange yellow lime cyan teal blue dark-blue purple magenta".split(" ");
var color_inv_order = "cyan teal blue dark-blue purple magenta dark-red red orange yellow lime green".split(" ");
var gray_names = ("black dark-gray light-gray white").split(" ")
var fire_names = ("black dark-red red orange yellow white cyan").split(" ")
var red_names = ("black dark-red red").split(" ")
var yellow_names = ("black orange yellow white").split(" ")
var green_names = ("teal green lime").split(" ")
var blue_names = ("black dark-blue blue").split(" ")
var purple_names = ("dark-blue purple magenta red").split(" ")
var dark_gray_names = ("black dark-blue teal dark-gray light-gray white").split(" ")
var color_alphabet = "abcdefghijklmnop";
var colors = {}
color_names.forEach(function(name, i){
colors[name.replace("-", "")] = i
colors[name] = i
})
colors.brown = 5
function get_inverse (n) { return colors[all_color_inv_order.indexOf(color_names[n])] }
function mirc_color (n) { return mod(n, 16)|0 }
function mirc_color_reverse (n) { return mod(-(n+1), 16)|0 }
function all_hue (n) { return colors[all_color_hue_order[mod(n, 16)|0]] }
function all_inv_hue (n) { return colors[all_color_inv_order[mod(n, 16)|0]] }
function hue (n) { return colors[color_hue_order[mod(n, 11)|0]] }
function rand_hue () { return colors[color_hue_order[randint(11)]] }
function rand_gray () { return colors[gray_names[randint(4)]] }
function inv_hue (n) { return colors[color_inv_order[mod(n, 11)|0]] }
function gray (n) { return colors[gray_names[mod(n, 4)|0]] }
function fire (n) { return colors[fire_names[mod(n, 7)|0]] }
function red (n) { return colors[red_names[mod(n, 3)|0]] }
function yellow (n) { return colors[yellow_names[mod(n, 4)|0]] }
function green (n) { return colors[green_names[mod(n, 3)|0]] }
function blue (n) { return colors[blue_names[mod(n, 3)|0]] }
function purple (n) { return colors[purple_names[mod(n, 4)|0]] }
function dark_gray (n) { return colors[dark_gray_names[mod(n, 4)|0]] }
var css_lookup = {
'rgb(255, 255, 255)': 'A',
'rgb(0, 0, 0)': 'B',
'rgb(0, 0, 127)': 'C',
'rgb(0, 147, 0)': 'D',
'red': 'E',
'rgb(127, 0, 0)': 'F',
'rgb(156, 0, 156)': 'G',
'rgb(252, 127, 0)': 'H',
'rgb(255, 255, 0)': 'I',
'rgb(0, 252, 0)': 'J',
'rgb(0, 147, 147)': 'K',
'rgb(0, 255, 255)': 'L',
'rgb(0, 0, 252)': 'M',
'rgb(255, 0, 255)': 'N',
'rgb(127, 127, 127)': 'O',
'rgb(210, 210, 210)': 'P',
};
var css_reverse_lookup = {}
Object.keys(css_lookup).forEach(function(color){
css_reverse_lookup[ css_lookup[color].charCodeAt(0) - 65 ] = color
})
var ansi_fg = [
97, // Bright White
30, // Black
94, // Blue
32, // Green
91, // Red
31, // Light Red
35, // Pink
33, // Yellow
93, // Light Yellow
92, // Light Green
36, // Cyan
96, // Light Cyan
34, // Light Blue
95, // Light Pink
90, // Grey
37, // Light Grey
]
var ansi_fg_import = {
97: 0, // Bright White
30: 1, // Black
94: 2, // Blue
32: 3, // Green
91: 4, // Red
31: 5, // Light Red
35: 6, // Pink
33: 7, // Yellow
93: 8, // Light Yellow
92: 9, // Light Green
36: 10, // Cyan
96: 11, // Light Cyan
34: 12, // Light Blue
95: 13, // Light Pink
90: 14, // Grey
37: 15, // Light Grey
}
var ansi_fg_bold_import = {
97: 0, // Bright White
30: 14, // Grey
94: 12, // Light Blue
32: 9, // Light Green
91: 4, // Light Red
31: 4, // Light Red
35: 13, // Light Pink
33: 8, // Light Yellow
93: 8, // Light Yellow
92: 9, // Light Green
36: 11, // Light Cyan
96: 11, // Light Cyan
34: 12, // Light Blue
95: 13, // Light Pink
90: 14, // Grey
37: 0, // Bright White
}
var ansi_bg = [
107, // Bright White
40, // Black
104, // Blue
42, // Green
101, // Red
41, // Light Red
45, // Pink
43, // Yellow
103, // Light Yellow
102, // Light Green
46, // Cyan
106, // Light Cyan
44, // Light Blue
105, // Light Pink
100, // Grey
47, // Light Grey
]
var ansi_bg_import = {
107: 0, // Bright White
40: 1, // Black
104: 2, // Blue
42: 3, // Green
101: 4, // Red
41: 5, // Light Red
45: 6, // Pink
43: 7, // Yellow
103: 8, // Light Yellow
102: 9, // Light Green
46: 10, // Cyan
106: 11, // Light Cyan
44: 12, // Light Blue
105: 13, // Light Pink
100: 14, // Grey
47: 15, // Light Grey
}

View File

@ -1,294 +0,0 @@
var blit = (function(){
var blit = {}
blit.and = blit.atop = function(A, B, x, y){
x = x || 0 ; y = y || 0
B.forEach(function(lex, u, v){
var cell = A.getCell(u+x, v+y)
if (cell && lex.opacity > 0) {
cell.assign(lex)
}
})
}
blit.or = blit.under = function(A, B, x, y){
x = x || 0 ; y = y || 0
B.forEach(function(lex, u, v){
var cell = A.getCell(u+x, v+y)
if (cell && cell.opacity == 0) {
cell.assign(lex)
}
})
}
// copy the region of A beginning at x,y into B
blit.copy_from = function(A, B, x, y){
x = x || 0 ; y = y || 0
B.forEach(function(lex, u, v){
var cell = A.getCell(u+x, v+y)
if (cell) {
lex.assign(cell)
}
})
}
blit.copy_toroidal_from = function(A, B, x, y){
x = x || 0 ; y = y || 0
B.forEach(function(lex, u, v){
var cell = A.get(u+x, v+y)
if (cell) {
lex.assign(cell)
}
})
}
blit.copy_to = function(A, B, x, y){
x = x || 0 ; y = y || 0
B.forEach(function(lex, u, v){
var cell = A.getCell(u+x, v+y)
if (cell) {
cell.assign(lex)
}
})
}
blit.invert = function(A, B, x, y){
x = x || 0 ; y = y || 0
B.forEach(function(lex, u, v){
var cell = A.getCell(u+x, v+y)
if (cell && lex.opacity > 0) {
cell.fg = get_inverse(cell.fg)
cell.bg = get_inverse(cell.bg)
}
})
}
var distance_rect = function(x, y, ratio){
return Math.sqrt((Math.pow(y * ratio, 2)) + Math.pow(x, 2))
}
var distance_square = function(x, y, ratio){
return Math.sqrt((Math.pow(y * ratio, 2)) + Math.pow(x * ratio, 2))
}
blit.circle = function(A, lex){
var hw = brush.w/2, hh = brush.h/2
var ratio, distance
if (brush.w === brush.h){
distance = distance_square
ratio = hw / hh * (brush.w === 3 || brush.w === 5 ? 1.2 : 1.05)
} else {
distance = distance_rect
ratio = hw / hh
}
A.forEach(function(lex,x,y) {
if (distance(x - hw + 0.5, y - hh + 0.5, ratio) > hw){
lex.clear()
}
})
}
blit.cross = function(A, lex){
A.forEach(function(lex,x,y) {
if ((x+y)%2) {
lex.clear()
}
})
}
blit.inverted_cross = function(A, lex){
// 1x1 brush should still draw something
if (A.w == 1 && A.h == 1) {
return
}
A.forEach(function(lex,x,y) {
if (!((x+y)%2)) {
lex.clear()
}
})
}
blit.square = function(A, lex){
// i.e. no transparency
}
return blit
})()
var draw = (function(){
var last_point = [0,0]
function down (e, lex, point) {
var w = canvas.w, h = canvas.h
erasing = (e.which == "3" || e.ctrlKey)
changed = true
if (e.shiftKey) {
line (lex, last_point, point, erasing)
}
else {
stamp (canvas, brush, point[0], point[1], erasing)
}
last_point[0] = point[0]
last_point[1] = point[1]
}
function set_last_point (e, point) {
last_point[0] = point[0]
last_point[1] = point[1]
}
function move (e, lex, point) {
var w = canvas.w, h = canvas.h
line(lex, last_point, point, erasing)
last_point[0] = point[0]
last_point[1] = point[1]
}
function move_toroidal (e, lex, point) {
var w = canvas.w, h = canvas.h
var src_x_quantile = quantile( last_point[0], w )
var src_y_quantile = quantile( last_point[1], h )
var dst_x_quantile = quantile( point[0], w )
var dst_y_quantile = quantile( point[1], h )
var src_x_mod = mod( last_point[0], w )
var src_y_mod = mod( last_point[1], h )
var dst_x_mod = mod( point[0], w )
var dst_y_mod = mod( point[1], h )
// if we've moved across the edge of the board, draw two lines
if (src_x_quantile != dst_x_quantile || src_y_quantile != dst_y_quantile) {
var xa, ya
if (src_x_quantile < dst_x_quantile) {
xa = [
[src_x_mod, dst_x_mod + w],
[src_x_mod-w, dst_x_mod],
]
}
else if (src_x_quantile == dst_x_quantile) {
xa = [
[src_x_mod, dst_x_mod],
[src_x_mod, dst_x_mod],
]
}
else {
xa = [
[src_x_mod, dst_x_mod-w],
[src_x_mod+w, dst_x_mod],
]
}
if (src_y_quantile < dst_y_quantile) {
ya = [
[src_y_mod, dst_y_mod + h],
[src_y_mod-h, dst_y_mod],
]
}
else if (src_y_quantile == dst_y_quantile) {
ya = [
[src_y_mod, dst_y_mod],
[src_y_mod, dst_y_mod],
]
}
else {
ya = [
[src_y_mod, dst_y_mod-h],
[src_y_mod+h, dst_y_mod],
]
}
line(lex, [ xa[0][0], ya[0][0] ], [ xa[0][1], ya[0][1] ], erasing)
line(lex, [ xa[1][0], ya[1][0] ], [ xa[1][1], ya[1][1] ], erasing)
}
else {
var x_a = mod( last_point[0], w )
var y_a = mod( last_point[1], h )
var x_b = mod( point[0], w )
var y_b = mod( point[1], h )
var last_point_mod = [x_b, y_b], point_mod = [x_a, y_a]
line(lex, last_point_mod, point_mod, erasing)
}
last_point[0] = point[0]
last_point[1] = point[1]
// y = point.y
}
function point (lex, x, y, erasing) {
stamp (canvas, brush, x, y, erasing)
}
function line (lex, a, b, erasing) {
var len = dist(a[0], a[1], b[0], b[1])
var bw = 1
var x, y, i;
for (var i = 0; i <= len; i += bw) {
x = lerp(i / len, a[0], b[0])
y = lerp(i / len, a[1], b[1])
stamp (canvas, brush, x, y, erasing)
}
}
function stamp (canvas, brush, x, y, erasing) {
var hh = brush.w/2|0
brush.forEach(function(lex, s, t){
s = round( s + x-hh )
t = round( t + y-hh )
if (s >= 0 && s < canvas.w && t >= 0 && t < canvas.h) {
if (lex.opacity === 0 && lex.char === ' ') return;
var aa = canvas.aa[t][s]
undo.save_lex(s, t, aa)
if (erasing) {
aa.erase(lex)
}
else {
aa.stamp(lex, brush)
}
}
})
}
function fill (lex, x, y) {
var q = [ [x,y] ]
var aa = canvas.aa
var target = aa[y][x].clone()
var n, w = 0, e = 0, j = 0
var kk = 0
// gets into a weird infinite loop if we don't break here.. :\
if (target.eq(lex)) { return }
LOOP: while (q.length) {
n = q.shift()
if (aa[n[1]][n[0]].ne(target)) {
continue LOOP
}
w = e = n[0]
j = n[1]
WEST: while (w > 0) {
if (aa[j][w-1].eq(target)) {
w = w-1
}
else {
break WEST
}
}
EAST: while (e < canvas.w-1) {
if (aa[j][e+1].eq(target)) {
e = e+1
}
else {
break EAST
}
}
for (var i = w; i <= e; i++) {
undo.save_lex(i, j, aa[j][i])
aa[j][i].assign(lex)
if (j > 0 && aa[j-1][i].eq(target)) {
q.push([ i, j-1 ])
}
if (j < canvas.h-1 && aa[j+1][i].eq(target)) {
q.push([ i, j+1 ])
}
}
}
}
var draw = {}
draw.down = down
draw.set_last_point = set_last_point
draw.move = move
draw.move_toroidal = move_toroidal
draw.stamp = stamp
draw.line = line
draw.point = point
draw.fill = fill
return draw
})()

View File

@ -1,148 +0,0 @@
function Lex (x,y) {
if (typeof x == "number") {
this.y = y
this.x = x
this.span = document.createElement("span")
}
else {
this.span = x
}
this.fg = colors.white
this.bg = colors.black
this.char = " "
this.opacity = 1
this.focused = false
}
Lex.prototype.build = function(){
if (isNaN(this.bg) || this.bg == Infinity || this.bg == -Infinity) this.bg = colors.black
if (isNaN(this.fg) || this.fg == Infinity || this.fg == -Infinity) this.fg = colors.black
this.span.className = this.css()
this.span.innerHTML = this.html()
}
Lex.prototype.css = function(){
return (
this.focused ?
"focused " : ""
) + (
this.opacity === 0 ?
"transparent f" + color_alphabet[modi(this.fg,16)] :
"f" + color_alphabet[modi(this.fg,16)] + " b" + color_alphabet[modi(this.bg,16)]
)
}
Lex.prototype.html = function(){
return this.char == " " ? "&nbsp;" : this.char || "&nbsp;"
}
Lex.prototype.read = function(){
this.char = this.span.innerHTML
return this.char
}
Lex.prototype.ascii = function(){
return this.char || " "
}
Lex.prototype.sanitize = function(){
switch (this.char) {
// case "%": return "%"
case undefined:
case "": return " "
default: return this.char
}
}
Lex.prototype.ansi = function(bg_, fg_){
var char = this.char || " "
var charIsNaN = isNaN(parseInt(char))
if ((bg_ == this.fg) && (fg_ == this.bg)) {
bg_ = this.bg; fg_ = this.fg
return [bg_, fg_, "\x1b[7m" + char]
} else if ((bg_ != this.bg) && (fg_ != this.fg)) {
bg_ = this.bg; fg_ = this.fg;
return [bg_, fg_, "\x1b[" + ansi_bg[bg_] + ";" + ansi_fg[fg_] + "m" + char]
} else if (bg_ != this.bg) {
bg_ = this.bg
return [bg_, fg_, "\x1b[" + ansi_bg[bg_] + "m" + char]
} else if (fg_ != this.fg) {
fg_ = this.fg
return [bg_, fg_, "\x1b[" + ansi_fg[fg_] + "m" + char]
}
}
Lex.prototype.mirc = function(bg_, fg_){
var char = this.char || " "
var charIsNaN = isNaN(parseInt(char))
if ((bg_ == this.fg) && (fg_ == this.bg)) {
bg_ = this.bg; fg_ = this.fg
return [bg_, fg_, "\x16" + char]
} else if ((bg_ == this.bg) && (fg_ != this.fg)) {
fg_ = this.fg
return [bg_, fg_, "\x03" + ((this.fg&15) < 10 && !charIsNaN ? "0" : "") + (this.fg&15) + char]
} else {
bg_ = this.bg; fg_ = this.fg
return [bg_, fg_, "\x03" + (this.fg&15) + "," + ((this.bg&15) < 10 && !charIsNaN ? "0" : "") + (this.bg&15) + char]
}
}
Lex.prototype.assign = function (lex){
this.fg = lex.fg
this.bg = lex.bg
this.char = lex.char
this.opacity = lex.opacity
this.build()
}
Lex.prototype.stamp = function (lex, brush){
if (brush.draw_fg) this.fg = lex.fg
if (brush.draw_bg && lex.opacity > 0) this.bg = lex.bg
if (brush.draw_char) this.char = lex.char
this.opacity = 1
this.build()
}
Lex.prototype.clone = function () {
var lex = new Lex (0,0)
lex.assign(this)
return lex
}
Lex.prototype.erase = function (){
this.fg = fillColor
this.bg = fillColor
this.char = " "
this.opacity = 1
this.build()
}
Lex.prototype.eq = function(lex){
return lex && this.fg == lex.fg && this.bg == lex.bg && this.char == lex.char
}
Lex.prototype.eqColor = function(lex){
return lex && this.fg == lex.fg && this.bg == lex.bg
}
Lex.prototype.ne = function(lex){
return ! this.eq(lex)
}
Lex.prototype.clear = function(){
this.bg = colors.black
this.fg = 0
this.char = " "
this.opacity = 0
this.build()
}
Lex.prototype.isClear = function(){
return this.bg == 1 && this.fg == 0 && this.char == " "
}
Lex.prototype.focus = function(){
if (focused) focused.blur()
this.span.classList.add('focused')
this.focused = true
focused = this
}
Lex.prototype.blur = function(){
focused = null
this.span && this.span.classList.remove('focused')
this.focused = false
this.onBlur && this.onBlur()
}
Lex.prototype.demolish = function(){
if (this.span.parentNode) { this.span.parentNode.removeChild(this.span) }
this.span = null
}
Lex.prototype.key = function(char, keyCode) {
if (! char) { return }
this.char = char
this.fg = brush.fg
this.build()
return true
}

View File

@ -1,515 +0,0 @@
function Matrix (w,h,f){
this.x = 0
this.y = 0
this.w = w
this.h = h
this.f = f
this.focus_x = 0
this.focus_y = 0
this.initialize()
}
Matrix.prototype.initialize = function(f){
var w = this.w || 1, h = this.h || 1, f = f || this.f
var aa = new Array (h)
for (var y = 0; y < h; y++) {
aa[y] = new Array (w)
for (var x = 0; x < w; x++) {
aa[y][x] = f(x,y)
}
}
this.aa = aa
}
Matrix.prototype.rebuild = function (){
this.demolish()
this.initialize()
this.append()
this.bind()
this.generate && this.generate()
this.focus_clamp()
check_if_lost_focus()
}
Matrix.prototype.clone = function () {
var base = this
var clone = new Matrix(this.w, this.h, function(x,y){
return base.getCell(x,y).clone()
})
clone.f = this.f
return clone
}
Matrix.prototype.assign = function (mat) {
var base = this
this.demolish()
this.w = mat.w
this.h = mat.h
// this.f = function(){}
this.initialize(function(x,y){
var el = mat.getCell(x,y).clone()
el.build()
return el
})
this.append()
this.bind()
check_if_lost_focus()
return this
}
Matrix.prototype.bind = function () {}
Matrix.prototype.demolish = function (){
this.forEach(function(lex){
lex.demolish()
})
while (this.wrapper && this.wrapper.firstChild) {
this.wrapper.removeChild(this.wrapper.firstChild);
}
this.aa.forEach(function(row){
row.length = 0
})
this.aa.length = 0
}
Matrix.prototype.forEach = function(f){
this.aa.forEach(function(row, y){
row.forEach(function(lex, x){
f(lex, x, y)
})
})
}
Matrix.prototype.focus_clamp = function(){
this.focus_x = clamp(this.focus_x, 0, this.w - 1)
this.focus_y = clamp(this.focus_y, 0, this.h - 1)
}
Matrix.prototype.focus_add = function(x, y){
this.focus(this.focus_x + x, this.focus_y + y)
}
Matrix.prototype.focus = function(x, y){
if (x === undefined) x = this.focus_x
if (y === undefined) y = this.focus_y
x = mod(x, this.w)
y = mod(y, this.h)
this.focus_x = x
this.focus_y = y
//focused_input = this
this.aa[y][x].focus()
}
Matrix.prototype.focusLex = function(y,x){
if (x < 0) {
y -= 1
}
if (x > this.aa[0].length) {
y += 1
}
this.aa[mod(y,this.h)][mod(x,this.w)].focus()
}
Matrix.prototype.clear = function(){
this.forEach(function(lex,x,y){ lex.clear() })
}
Matrix.prototype.erase = function(){
this.forEach(function(lex,x,y){ lex.erase() })
}
Matrix.prototype.fill = function(lex){
this.fg = lex.fg
this.bg = lex.bg
this.char = lex.char
this.opacity = lex.opacity
this.forEach(function(el,x,y){
el.assign(lex)
el.build()
})
}
Matrix.prototype.build = function(){
this.forEach(function(lex,x,y){
lex.build()
})
}
Matrix.prototype.append = function(wrapper){
wrapper = this.wrapper = wrapper || this.wrapper
if (! this.wrapper) return
this.aa.forEach(function(row, y){
var div = document.createElement("div")
row.forEach(function(lex, x) {
div.appendChild(lex.span)
})
wrapper.appendChild( div )
})
}
Matrix.prototype.region = function(w,h,x,y) {
w = w || 1
h = h || 1
x = x || 0
y = y || 0
var parent = this
var mat = new Matrix(w, h, function(x,y){
return parent.aa[y][x]
})
mat.f = this.f
return mat
}
Matrix.prototype.setCell = function(lex,x,y){
this.aa[y] && this.aa[y][x] && this.aa[y][x].assign(lex)
}
Matrix.prototype.getCell = function(x,y){
if (this.aa[y] && this.aa[y][x]) return this.aa[y][x]
else return null
}
Matrix.prototype.get = function(x,y){
y = floor(mod(y || 0, this.h))
x = floor(mod(x || 0, this.w))
if (this.aa[y] && this.aa[y][x]) return this.aa[y][x]
else return null
}
Matrix.prototype.resize = function(w,h){
w = w || canvas.w
h = h || canvas.h
var div, row, lex
var f = this.f, old_h = this.aa.length, old_w = this.aa[0].length
var wrapper = this.wrapper
w = max(w, 1)
h = max(h, 1)
if (h < old_h) {
for (var y = old_h; y > h; y--) {
row = this.aa.pop()
div = row[0].span.parentNode
row.forEach(function(lex, x){
lex.demolish()
})
div.parentNode.removeChild(div)
}
}
else if (h > old_h) {
for (var y = old_h; y < h; y++) {
div = document.createElement("div")
wrapper.appendChild( div )
this.aa[y] = new Array (w)
for (var x = 0; x < w; x++) {
lex = this.aa[y][x] = f(x,y)
div.appendChild(lex.span)
}
}
}
if (w < old_w) {
this.aa.forEach(function(row, y){
while (row.length > w) {
lex = row.pop()
lex.demolish()
}
})
}
else if (w > old_w) {
this.aa.forEach(function(row, y){
div = row[0].span.parentNode
for (var x = row.length; x < w; x++) {
lex = row[x] = f(x,y)
div.appendChild(lex.span)
}
})
}
this.w = w
this.h = h
this.bind && this.bind()
this.focus_clamp()
if (this.wrapper && this.wrapper.parentNode != document.body) {
this.resize_wrapper()
}
}
Matrix.prototype.resize_wrapper = function(){
var cell = canvas.aa[0][0].span
var cw = cell.offsetWidth
var ch = cell.offsetHeight
// if (canvas.grid) { ch++ }
var width = cw * this.aa[0].length
var height = ch * this.aa.length
if (canvas.grid) { width++; height++ }
this.wrapper.parentNode.style.height = ""
this.wrapper.style.width =
this.wrapper.parentNode.style.width = (width) + "px"
this.wrapper.style.top = ""
}
Matrix.prototype.ascii = function () {
var lines = this.aa.map(function(row, y){
var last, line = ""
row.forEach(function(lex, x) {
line += lex.ascii()
})
return line // .replace(/\s+$/,"")
})
var txt = lines.join("\n")
return txt
}
Matrix.prototype.ansi = function (opts) {
var lines = this.aa.map(function(row, y){
var last, line = "", bg_ = -1, fg_ = -1
row.forEach(function(lex, x) {
if (lex.eqColor(last)) {
line += lex.sanitize()
}
else {
[bg_, fg_, line_] = lex.ansi(bg_, fg_)
line += line_; last = lex;
}
})
return line
})
var txt = lines.filter(function(line){ return line.length > 0 }).join('\n')
return txt
}
Matrix.prototype.mirc = function (opts) {
var cutoff = false
var lines = this.aa.map(function(row, y){
var last, line = "", bg_ = -1, fg_ = -1
row.forEach(function(lex, x) {
if (lex.eqColor(last)) {
line += lex.sanitize()
}
else {
[bg_, fg_, line_] = lex.mirc(bg_, fg_)
line += line_; last = lex;
}
})
if (opts && opts.cutoff && line.length > opts.cutoff) {
cutoff = true
}
return line
})
var txt = lines.filter(function(line){ return line.length > 0 }).join('\n')
if (cutoff) {
txt = new String(txt)
txt.cutoff = true
}
return txt
}
var undo = (function(){
var max_states = 200;
// undotimetotal = 0;
var stack = {undo: [], redo: []};
var current_undo = null;
var dom = {undo: undo_el, redo: redo_el};
dom.undo.is_visible = dom.redo.is_visible = false
var LexState = function(lex){
this.fg = lex.fg;
this.bg = lex.bg;
this.char = lex.char;
this.opacity = lex.opacity;
};
var update_dom_visibility = function(type){
var el = dom[type]
if (el.is_visible){
if (stack[type].length === 0) {
el.classList.add('hidden')
el.is_visible = false
}
} else if (stack[type].length > 0){
el.classList.remove('hidden')
el.is_visible = true
}
}
var update_dom = function(){
update_dom_visibility('undo')
update_dom_visibility('redo')
}
// state is an undo or redo state that might contain these props
// { lexs: {'0,0': LexState, ...}, // for sparse lex changes (eg brush, fill)
// focus: {x:, y: },
// size: {w:, h: },
// rects: [{x:, y:, w:, h:, lexs: [LexState, ...]}, ...]
// }
var new_state = function(){
var state = {lexs:{}};
save_focus(canvas.focus_x, canvas.focus_y, state)
return state
}
var new_redo = function(){
return new_state()
}
var new_undo = function(){
current_undo = new_state()
stack.redo = []
stack.undo.push(current_undo)
if (stack.undo.length > max_states) stack.undo.shift();
update_dom()
return current_undo
}
var save_focus = function(x, y, state){
state = state || current_undo
state.focus = {x:x, y:y}
}
var save_size = function(w, h, state){
state = state || current_undo
state.size = {w:w, h:h};
}
// the reason for stringifying the x y coords is so that each
// coordinate is saved only once in an undo state.
// otherwise there would be problems with, eg, a brush stroke
// that passed over the same grid cell twice.
var save_lex = function(x, y, lex, state){
// var start = Date.now()
state = state || current_undo
var lexs = state.lexs;
var xy = x + "," + y;
if (xy in lexs) return;
lexs[xy] = new LexState(lex)
// undotimetotal += Date.now() - start
}
var save_focused_lex = function(state){
state = state || current_undo
var x = canvas.focus_x
var y = canvas.focus_y
save_lex(x, y, canvas.aa[y][x], state)
}
var save_rect = function(xpos, ypos, w, h, state){
if (w === 0 || h === 0) return;
state = state || current_undo;
state.rects = state.rects || []
var aa = canvas.aa;
var rect = {x: xpos, y: ypos, w: w, h: h, lexs: []}
var lexs = rect.lexs
var xlen = xpos + w
var ylen = ypos + h
for (var y = ypos; y < ylen; y++){
var aay = aa[y]
for (var x = xpos; x < xlen; x++){
lexs.push(new LexState(aay[x]))
}
}
state.rects.push(rect)
}
var save_resize = function(w, h, old_w, old_h, state){
state = state || current_undo
save_size(old_w, old_h, state)
if (old_w > w){
// .---XX
// | XX
// |___XX
save_rect(w, 0, old_w - w, old_h, state)
if (old_h > h){
// .----.
// | |
// XXXX_|
save_rect(0, h, w, old_h - h, state)
}
} else if (old_h > h){
// .----.
// | |
// XXXXXX
save_rect(0, h, old_w, old_h - h, state)
}
}
var restore_state = function(state){
// all redo states will have a cached undo state on them
// an undo state might have a cached redo state
// if it doesn't have one, generate one
var make_redo = ! ('redo' in state || 'undo' in state);
var aa = canvas.aa
var lex, lexs;
if (make_redo){
state.redo = new_redo()
// copy saved rects that intersect with current canvas size
// important to do this before resizing canvas
if ('rects' in state){
for (var ri=0, rect; rect=state.rects[ri]; ri++){
if (rect.x >= canvas.w ||
rect.y >= canvas.h) continue;
var w = Math.min(rect.w, canvas.w - rect.x)
var h = Math.min(rect.h, canvas.h - rect.y)
save_rect(rect.x, rect.y, w, h, state.redo)
}
}
if ('size' in state){
save_resize(state.size.w, state.size.h, canvas.w, canvas.h, state.redo)
}
}
if ('size' in state){
canvas.resize(state.size.w, state.size.h, true);
}
if ('rects' in state){
for (var ri=0, rect; rect=state.rects[ri]; ri++){
lexs = rect.lexs
for (var li=0; lex=lexs[li]; li++){
var x = (li % rect.w) + rect.x
var y = ((li / rect.w)|0) + rect.y
aa[y][x].assign(lex)
}
}
}
lexs = state.lexs
for (var key in lexs){
var xy = key.split(',');
lex = aa[xy[1]][xy[0]]
if (make_redo)
save_lex(xy[0], xy[1], lex, state.redo)
lex.assign(lexs[key])
}
if ('focus' in state){
canvas.focus_x = state.focus.x
canvas.focus_y = state.focus.y
if (current_canvas === canvas){
canvas.focus()
}
}
}
var undo = function(){
var state = stack.undo.pop();
if (!state) return;
restore_state(state)
// now take the applied undo state and store it on the redo state
// and push the redo state to the redo stack
state.redo.undo = state
stack.redo.push(state.redo)
delete state.redo
update_dom()
}
var redo = function(){
var state = stack.redo.pop();
if (!state) return;
restore_state(state)
state.undo.redo = state
stack.undo.push(state.undo)
delete state.undo
update_dom()
}
return {
stack: stack,
new: new_undo,
// new_redo: new_redo,
save_focus: save_focus,
save_size: save_size,
save_lex: save_lex,
save_focused_lex: save_focused_lex,
save_rect: save_rect,
save_resize: save_resize,
undo: undo,
redo: redo
}
})()

View File

@ -1,138 +0,0 @@
var brush = (function(){
var brush = new Matrix (5, 5, function(x,y){
var lex = new Lex (x,y)
lex.build()
return lex
})
brush.modified = false
brush.mask = blit.circle
brush.generate = function(){
brush.fill(brush)
brush.mask(brush)
}
brush.bind = function(){
var last_point = [0,0]
var dragging = false
var erasing = false
brush.forEach(function(lex, x, y){
if (lex.bound) return
lex.bound = true
var point = [x,y]
lex.span.addEventListener('contextmenu', function(e){
e.preventDefault()
})
lex.span.addEventListener('mousedown', function(e){
e.preventDefault()
current_canvas = brush
brush.modified = true
dragging = true
erasing = (e.which == "3" || e.ctrlKey)
if (erasing) {
lex.clear()
}
else {
fillColor = brush.bg
lex.assign(brush)
}
brush.focus(x, y)
})
lex.span.addEventListener('mousemove', function(e){
e.preventDefault()
if (! dragging) {
return
}
erasing = (e.which == "3" || e.ctrlKey)
if (erasing) {
lex.clear()
}
else {
lex.assign(brush)
}
brush.focus(x, y)
})
})
window.addEventListener('mouseup', function(e){
dragging = erasing = false
})
}
brush.resize = function(w, h){
w = this.w = clamp(w, this.min, this.max)
h = this.h = clamp(h, this.min, this.max)
brush.rebuild()
controls.brush_w.char = "" + w
controls.brush_w.build()
controls.brush_h.char = "" + h
controls.brush_h.build()
}
brush.size_add = function(w, h){
brush.resize(brush.w + w, brush.h + h)
}
brush.expand = function(i){
brush.size_add(i, i)
}
brush.contract = function(i){
brush.size_add(-i, -i)
}
brush.load = function(lex){
brush.char = lex.char
brush.fg = lex.fg
brush.bg = lex.bg
brush.opacity = 1
}
brush.min = 1
brush.max = 100
brush.char = " "
brush.fg = 0
brush.bg = 1
brush.opacity = 1
brush.draw_fg = true
brush.draw_bg = true
brush.draw_char = true
return brush
})()
var custom = (function(){
var exports = {}
exports.clone = function (){
var new_brush = brush.clone()
var wrapper = document.createElement("div")
wrapper.className = "custom"
new_brush.append(wrapper)
custom_wrapper.appendChild(wrapper)
// store in localstorage?
wrapper.addEventListener("click", function(e){
if (e.shiftKey) {
wrapper.parentNode.removeChild(wrapper)
delete new_brush
} else {
// load this brush
exports.load(new_brush)
}
})
}
exports.load = function(new_brush){
brush.assign( new_brush )
}
return exports
})()

View File

@ -1,102 +0,0 @@
var canvas = current_canvas = (function(){
var cols = 100
var rows = 30
var canvas = new Matrix (cols, rows, function(x,y){
var lex = new Lex (x,y)
lex.build()
return lex
})
canvas.bind = function(){
canvas.forEach(function(lex, x, y){
if (lex.bound) return
lex.bound = true
var point = [x,y]
lex.span.addEventListener('contextmenu', function(e){
e.preventDefault()
})
lex.span.addEventListener('mousedown', function(e){
e.preventDefault()
dragging = true
current_canvas = canvas
if (e.altKey) {
if (e.shiftKey) {
blit.copy_from(canvas, brush, floor(x-brush.w/2), floor(y-brush.h/2))
brush.mask(brush)
draw.set_last_point(e, point)
}
else {
brush.load(lex)
brush.generate()
dragging = false
}
return
}
else if (drawing) {
undo.new()
draw.down(e, lex, point)
}
else if (selecting) {
selection.down(e, lex, point)
}
else if (transforming) {
transform.down(e, lex, point)
}
else if (filling) {
undo.new()
draw.fill(brush, x, y)
}
canvas.focus(x, y)
})
lex.span.addEventListener("mousemove", function(e){
mouse.x = x
mouse.y = y
if (! dragging) return
if (drawing) {
draw.move(e, lex, point)
}
else if (selecting) {
selection.move(e, lex, point)
}
else if (transforming) {
transform.move(e, lex, point)
}
canvas.focus(x, y)
})
})
}
canvas.min = 1
canvas.max = 999
// canvas.resize(1, 1, true) // wont create undo state
canvas.resize = function(w, h, no_undo){
var old_w = this.w, old_h = this.h
w = this.w = clamp(w, this.min, this.max)
h = this.h = clamp(h, this.min, this.max)
if (old_w === w && old_h === h) return;
if (!no_undo){
undo.new()
undo.save_resize(w, h, old_w, old_h)
}
canvas.__proto__.resize.call(canvas, w, h)
controls.canvas_w.char = "" + w
controls.canvas_w.build()
controls.canvas_h.char = "" + h
controls.canvas_h.build()
}
canvas.size_add = function(w, h){
canvas.resize(canvas.w + w, canvas.h + h)
}
return canvas
})()

View File

@ -1,259 +0,0 @@
var controls = (function(){
var controls = {}
controls.cross = new Tool (cross_el)
controls.cross.use = function(){
if (brush.mask == blit.cross) {
controls.cross.el.innerHTML = "ssoɹɔ"
brush.mask = blit.inverted_cross
}
else {
controls.cross.el.innerHTML = "cross"
brush.mask = blit.cross
}
brush.generate()
drawing = true
brush.modified = false
}
controls.cross.done = function(){
controls.cross.el.innerHTML = "cross"
drawing = false
}
controls.circle = new Tool (circle_el)
controls.circle.use = function(){
brush.mask = blit.circle
brush.generate()
drawing = true
brush.modified = false
}
controls.circle.done = function(){
drawing = false
}
controls.square = new Tool (square_el)
controls.square.use = function(){
brush.mask = blit.square
brush.generate()
brush.modified = false
drawing = true
}
controls.square.done = function(){
drawing = false
}
controls.text = new Tool (text_el)
controls.text.use = function(){
current_filetool && current_filetool.blur()
}
controls.select = new Tool (select_el)
controls.select.use = function(){
selection.show()
}
controls.select.done = function(){
selection.hide()
}
controls.rotate = new Tool (rotate_el)
controls.rotate.use = function(){
transform.set_mode('rotate')
}
controls.rotate.done = function(){
transform.done()
}
controls.scale = new Tool (scale_el)
controls.scale.use = function(){
transform.set_mode('scale')
}
controls.scale.done = function(){
transform.done()
}
controls.slice = new Tool (slice_el)
controls.slice.use = function(){
transform.set_mode('slice')
}
controls.slice.done = function(){
transform.done()
}
controls.translate = new Tool (translate_el)
controls.translate.use = function(){
transform.set_mode('translate')
}
controls.translate.done = function(){
transform.done()
}
controls.fill = new Tool (fill_el)
controls.fill.use = function(){
filling = true
document.body.classList.add("bucket")
}
controls.fill.done = function(){
filling = false
document.body.classList.remove("bucket")
}
controls.undo = new BlurredTool (undo_el)
controls.undo.use = function(){
undo.undo()
}
controls.redo = new BlurredTool (redo_el)
controls.redo.use = function(){
undo.redo()
}
controls.clear = new BlurredTool (clear_el)
controls.clear.use = function(){
undo.new()
undo.save_rect(0, 0, canvas.w, canvas.h)
canvas.erase()
current_filetool && current_filetool.blur()
}
controls.grid = new BlurredCheckbox (grid_el)
controls.grid.memorable = true
controls.grid.use = function(state){
state = typeof state == "boolean" ? state : ! document.body.classList.contains("grid")
document.body.classList[ state ? "add" : "remove" ]('grid')
letters.grid = palette.grid = canvas.grid = state
canvas.resize_wrapper()
palette.resize_wrapper()
letters.resize_wrapper()
if (! selection.hidden) selection.reposition()
this.update( state )
}
ClipboardTool = FileTool.extend({
blur: function(){
this.__blur()
clipboard.export_hide()
clipboard.import_hide()
}
})
controls.save = new ClipboardTool (save_el)
controls.save.use = function(){
clipboard.export_show()
clipboard.export_mode()
}
controls.load = new ClipboardTool (load_el)
controls.load.use = function(){
clipboard.import_show()
clipboard.import_mode()
}
controls.load_format = new RadioGroup(import_format_el)
controls.load_format.name = 'load_format'
controls.load_format.memorable = true
var cs = controls.load_format.controls
//
controls.save_format = new RadioGroup(export_format_el)
controls.save_format.name = 'save_format'
controls.save_format.memorable = true
var cs = controls.save_format.controls
cs.mirc.use = cs.ansi.use = cs.ascii.use = function(){
clipboard.export_data()
}
//
controls.experimental_palette = new HiddenCheckbox (experimental_palette_toggle)
controls.experimental_palette.memorable = true
controls.experimental_palette.use = function(state){
var state = palette.experimental(state)
this.update(state)
}
//
controls.fg = new BlurredCheckbox (fg_checkbox)
controls.fg.use = function(state){
brush.draw_fg = state || ! brush.draw_fg
this.update(brush.draw_fg)
}
controls.bg = new BlurredCheckbox (bg_checkbox)
controls.bg.use = function(state){
brush.draw_bg = state || ! brush.draw_bg
this.update(brush.draw_bg)
}
controls.char = new BlurredCheckbox (char_checkbox)
controls.char.use = function(state){
brush.draw_char = state || ! brush.draw_char
this.update(brush.draw_char)
}
controls.vertical = new BlurredCheckbox (vertical_checkbox)
controls.vertical.memorable = true
controls.vertical.use = function(state){
canvas.vertical = typeof state == "boolean" ? state : ! canvas.vertical
controls.vertical.refresh()
}
controls.vertical.refresh = function(){
if (canvas.vertical) {
document.body.classList.add("vertical")
}
else {
document.body.classList.remove("vertical")
}
palette.repaint()
letters.repaint()
this.update(canvas.vertical)
}
//
controls.brush_w = new Lex (brush_w_el)
controls.brush_h = new Lex (brush_h_el)
controls.canvas_w = new Lex (canvas_w_el)
controls.canvas_h = new Lex (canvas_h_el)
// bind
controls.bind = function(){
for (var n in controls){
var control = controls[n]
if (typeof control === 'object' && 'bind' in control){
control.bind()
}
}
[
controls.brush_w,
controls.brush_h,
controls.canvas_w,
controls.canvas_h
].forEach(function(lex){
lex.span.addEventListener('mousedown', function(e){
lex.focus()
})
});
controls.brush_w.key = keys.single_numeral_key(controls.brush_w, function(w){ brush.resize(w, brush.h) })
controls.brush_w.raw_key = keys.arrow_key(function(w){ brush.size_add(w, 0) })
controls.brush_h.key = keys.single_numeral_key(controls.brush_h, function(h){ brush.resize(brush.w, h) })
controls.brush_h.raw_key = keys.arrow_key(function(h){ brush.size_add(0, h) })
controls.canvas_w.key = keys.multi_numeral_key(controls.canvas_w, 3)
controls.canvas_w.onBlur = keys.multi_numeral_blur(controls.canvas_w, function(w){ canvas.resize(w, canvas.h) })
controls.canvas_w.raw_key = keys.arrow_key(function(w){ canvas.size_add(w, 0) })
controls.canvas_h.key = keys.multi_numeral_key(controls.canvas_h, 3)
controls.canvas_h.onBlur = keys.multi_numeral_blur(controls.canvas_h, function(h){ canvas.resize(canvas.w, h) })
controls.canvas_h.raw_key = keys.arrow_key(function(h){ canvas.size_add(0, h) })
add_custom_el.addEventListener("click", function(){
custom.clone()
})
}
return controls
})()

View File

@ -1,209 +0,0 @@
var keys = (function(){
var keys = {}
keys.bind = function(){
cursor_input.addEventListener('keydown', function(e){
// console.log("keycode:", e.keyCode)
if (e.altKey) {
document.body.classList.add("dropper")
}
switch (e.keyCode) {
case 27: // esc
if (!selection.hidden && current_canvas === canvas){
selection.hide()
selection.show()
} else if (focused){
focused.blur()
}
return
}
if (window.focused && focused.raw_key) {
focused.raw_key(e)
return
}
switch (e.keyCode) {
case 219: // [
if (current_tool.name != "text") {
e.preventDefault()
brush.contract(1)
brush.modified = false
check_if_lost_focus()
}
break
case 221: // ]
if (current_tool.name != "text") {
e.preventDefault()
brush.expand(1)
brush.modified = false
}
break
case 8: // backspace
e.preventDefault()
if (current_canvas === canvas)
undo.new()
current_canvas.focus_add(-1, 0)
if (current_canvas === canvas)
undo.save_focused_lex()
focused.char = " "
focused.build()
return
case 13: // return
e.preventDefault()
current_canvas.focusLex(focused.y, focused.x+1)
return
case 38: // up
e.preventDefault()
current_canvas.focus_add(0, -1)
break
case 40: // down
e.preventDefault()
current_canvas.focus_add(0, 1)
break
case 37: // left
e.preventDefault()
current_canvas.focus_add(-1, 0)
break
case 39: // right
e.preventDefault()
current_canvas.focus_add(1, 0)
break
// use typical windows and os x shortcuts
// undo: ctrl-z or cmd-z
// redo: ctrl-y or shift-cmd-z
case 89: // y
if (!e.ctrlKey && !e.metaKey) break;
e.preventDefault();
undo.redo();
break
case 90: // z
if (!e.ctrlKey && !e.metaKey) break;
e.preventDefault();
if (e.shiftKey)
undo.redo();
else
undo.undo();
break
// default:
// if (focused) { focused.key(undefined, e.keyCode) }
}
})
cursor_input.addEventListener('input', function(e){
/*
if (! e.metaKey && ! e.ctrlKey && ! e.altKey) {
e.preventDefault()
}
*/
var char = cursor_input.value
cursor_input.value = ""
// console.log("input:", char)
if (current_tool.name != "text" && ! brush.modified) {
brush.char = char
if (char == " ") {
brush.bg = brush.fg
}
else if (brush.bg != fillColor) {
brush.fg = brush.bg
brush.bg = fillColor
}
brush.rebuild()
}
if (focused && char) {
var y = focused.y, x = focused.x
if (current_canvas === canvas){
undo.new()
undo.save_focused_lex()
}
var moving = focused.key(char, e.keyCode)
if ( ! moving || ! ('y' in focused && 'x' in focused) ) { return }
current_canvas.focus_add(1, 0)
}
})
cursor_input.addEventListener("keyup", function(e){
if (! e.altKey) {
document.body.classList.remove("dropper")
}
})
}
keys.int_key = function (f) {
return function (key, keyCode) {
var n = parseInt(key)
! isNaN(n) && f(n)
}
}
keys.arrow_key = function (fn) {
return function (e){
switch (e.keyCode) {
case 38: // up
e.preventDefault()
fn(1)
break
case 40: // down
e.preventDefault()
fn(-1)
break
}
}
}
keys.left_right_key = function (fn) {
return function (e){
switch (e.keyCode) {
case 39: // right
e.preventDefault()
fn(1)
break
case 38: // up
case 40: // down
e.preventDefault()
fn(0)
break
case 37: // left
e.preventDefault()
fn(-1)
break
}
}
}
keys.single_numeral_key = function (lex, fn) {
return keys.int_key(function(n, keyCode){
if (n == 0) n = 10
lex.blur()
fn(n)
})
}
keys.multi_numeral_key = function (lex, digits){
return keys.int_key(function(n, keyCode){
lex.read()
if (lex.char.length < digits) {
n = parseInt(lex.char) * 10 + n
}
lex.char = ""+n
lex.build()
})
}
keys.multi_numeral_blur = function (lex, fn){
return function(){
var n = parseInt(lex.char)
if (isNaN(n)) return
fn(n)
}
}
return keys
})()
function check_if_lost_focus() {
if (! window.focused || ! window.focused.span)
window.focused = canvas.aa[0][0]
}

View File

@ -1,206 +0,0 @@
var letters = (function(){
var last_charset = ""
var charset_index = 0
var charsets = [
'Basic Latin',
'Latin-1 Supplement',
'Box Drawing',
'Block Elements',
]
var letters = new Matrix (1, 1, function(x,y){
var lex = new Lex (x,y)
return lex
})
letters.charset = ""
letters.repaint = function(charset){
letters.charset = charset = charset || last_charset
last_charset = charset
var chars = unicode.block(charset, 32)
if (chars[0] != " ") chars.unshift(" ")
if (canvas.vertical) {
letters.resize( Math.ceil( chars.length / 16 ), 16 )
}
else {
letters.resize( 32, Math.ceil( chars.length / 32 ) )
}
var i = 0
letters.forEach(function(lex,x,y){
if (canvas.vertical) { x=x^y;y=x^y;x=x^y }
var char = chars[i++]
if (palette.chars.indexOf(brush.char) > 1) {
lex.bg = brush.fg
lex.fg = brush.bg
}
else {
lex.bg = colors.black
lex.fg = brush.fg == fillColor ? colors.black : brush.fg
}
lex.char = char
lex.opacity = 1
lex.build()
})
}
letters.bind = function(){
letters.forEach(function(lex,x,y){
if (lex.bound) return
lex.bound = true
lex.span.addEventListener('mousedown', function(e){
e.preventDefault()
if (e.shiftKey) {
charset_index = (charset_index+1) % charsets.length
letters.repaint(charsets[charset_index])
return
}
else if (e.ctrlKey || e.which == 3) {
brush.char = lex.char
brush.bg = brush.fg
brush.fg = fillColor
}
else {
brush.char = lex.char
if (lex.char == " ") {
brush.bg = brush.fg
}
else if (brush.bg != fillColor) {
brush.fg = brush.bg
brush.bg = fillColor
}
}
if (! brush.modified) {
brush.generate()
}
palette.repaint()
})
lex.span.addEventListener('contextmenu', function(e){
e.preventDefault()
})
})
}
return letters
})()
var palette = (function(){
var palette = new Matrix (32, 2, function(x,y){
var lex = new Lex (x,y)
return lex
})
var palette_index = localStorage.getItem("ascii.palette") || 1
var palette_list = [all_hue, all_inv_hue, mirc_color, mirc_color_reverse]
var palette_fn = palette_list[palette_index]
var dither = {
aa: '▓▒░ ',
a: '▓',
b: '▒',
c: '░',
d: ' ',
p: function(n){
return dither.aa[Math.floor(Math.abs(n) % 4)]
}
}
palette.chars = " " + dither.a + dither.b + dither.c
palette.repaint = function(){
var xw = use_experimental_palette ? 5 : 2
if (canvas.vertical) {
palette.resize( xw, 16 )
}
else {
palette.resize( 32, xw )
}
palette.forEach(function(lex,x,y){
if (canvas.vertical) { x=x^y;y=x^y;x=x^y;x*=2 }
if (y < 2) {
lex.bg = palette_fn(x>>1)
lex.fg = palette_fn(x>>1)
}
else {
lex.bg = fillColor
lex.fg = palette_fn(x>>1)
}
lex.char = palette.chars[y]
lex.opacity = 1
lex.build()
if (lex.char == "_") lex.char = " "
})
}
palette.repaint()
var use_experimental_palette = false
palette.experimental = function(state){
use_experimental_palette = typeof state == "boolean" ? state : ! use_experimental_palette
use_experimental_palette ? palette.resize(32, 5) : palette.resize(32, 2)
palette.repaint()
return use_experimental_palette
}
palette.bind = function(){
palette.forEach(function(lex, x, y){
if (lex.bound) return
lex.bound = true
lex.span.addEventListener('mousedown', function(e){
e.preventDefault()
if (e.shiftKey) {
palette_index = (palette_index+1) % palette_list.length
localStorage.setItem("ascii.palette", palette_index)
palette_fn = palette_list[palette_index]
palette.repaint()
return
}
if (e.ctrlKey || e.which == 3) return
if (brush.char == " " && lex.char == " ") {
brush.fg = lex.fg
brush.bg = lex.bg
brush.char = lex.char
}
else if (lex.char != " ") {
brush.fg = lex.bg
brush.bg = lex.fg
brush.char = lex.char
}
else {
brush.fg = lex.bg
brush.bg = fillColor
// brush.char = lex.char
}
brush.opacity = lex.opacity
if (! brush.modified) {
brush.generate()
}
if (filling || e.ctrlKey) {
fillColor = lex.bg
}
letters.repaint()
})
lex.span.addEventListener('contextmenu', function(e){
e.preventDefault()
fillColor = y ? lex.fg : lex.bg
palette.repaint()
brush.fg = lex.fg
brush.char = lex.char
brush.opacity = lex.opacity
brush.generate()
brush_wrapper.style.borderColor = css_reverse_lookup[fillColor]
return
})
})
}
brush_wrapper.style.borderColor = css_reverse_lookup[fillColor]
return palette
})()

View File

@ -1,159 +0,0 @@
var selection = (function(){
var creating = false, moving = false, copying = false
var selection_canvas = new Matrix (1, 1, function(x,y){
var lex = new Lex (x,y)
lex.build()
return lex
})
var selector_el = document.createElement("div")
selector_el.className = "selector_el"
selection_canvas.append(selector_el)
document.body.appendChild(selector_el)
// in selection mode..
// - we start by clicking the canvas. this positions the selection, and copies
// the character
// - then we drag down and to the right. this resizes the selection and pushes new
// rows and columns. each of these copies the character underneath.
// - on mouseup, the selection is locked. then..
// - drag the selection to move it -- this "cuts" it and leaves a blank space on the canvas.
// - shift-drag the selection to copy it
var a = [0, 0]
var b = [0, 0]
var c = [0, 0]
var d = [0, 0]
function reset () {
a[0] = a[1] = b[0] = b[1] = 0
}
function left (a,b) { return min(a[0],b[0]) }
function top (a,b) { return min(a[1],b[1]) }
function right (a,b) { return max(a[0],b[0]) }
function bottom (a,b) { return max(a[1],b[1]) }
function width (a,b) { return abs(a[0]-b[0])+1 }
function height (a,b) { return abs(a[1]-b[1])+1 }
function mag_x (a,b) { return a[0]-b[0] }
function mag_y (a,b) { return a[1]-b[1] }
function orient (a,b) {
var l = left(a,b), m = top(a,b), n = right(a,b), o = bottom(a,b)
a[0] = l ; a[1] = m ; b[0] = n ; b[1] = o
}
function contains (a,b,point) {
var contains_x = a[0] <= point[0] && point[0] <= b[0]
var contains_y = a[1] <= point[1] && point[1] <= b[1]
return (contains_x && contains_y)
}
function reposition (aa, bb) {
aa = aa || a
bb = bb || b
var cell = canvas.aa[top(aa, bb)][left(aa, bb)].span
var cell_left = cell.offsetLeft
var cell_top = cell.offsetTop
var cell_width = cell.offsetWidth
var cell_height = cell.offsetHeight
var w = width(aa, bb)
var h = height(aa, bb)
selector_el.style.top = (cell_top-1) + "px"
selector_el.style.left = (cell_left-1) + "px"
selector_el.style.width = (cell_width*w+1) + "px"
selector_el.style.height = (cell_height*h+1) + "px"
}
function down (e, lex, point){
if ( ! contains(a,b,point) ) {
copying = false
moving = false
creating = true
a[0] = point[0]
a[1] = point[1]
b[0] = point[0]
b[1] = point[1]
reposition(a,b)
selection.hidden = false
selector_el.classList.add("creating")
} else {
copying = false
moving = true
creating = false
c[0] = point[0]
c[1] = point[1]
d[0] = point[0]
d[1] = point[1]
}
show()
selector_el.classList.remove("dragging")
}
function move (e, lex, point){
if (creating) {
b[0] = point[0]
b[1] = point[1]
reposition(a,b)
}
else if (moving) {
d[0] = point[0]
d[1] = point[1]
var dx = - clamp( mag_x(c,d), b[0] - canvas.w + 1, a[0] )
var dy = - clamp( mag_y(c,d), b[1] - canvas.h + 1, a[1] )
reposition( [ a[0] + dx, a[1] + dy ], [ b[0] + dx, b[1] + dy ])
}
else if (copying) {
}
}
function up (e) {
if (creating) {
orient(a,b)
selection_canvas.resize(width(a,b), height(a,b))
reposition(a,b)
blit.copy_from( canvas, selection_canvas, a[0], a[1] )
selection_canvas.build()
selector_el.classList.remove("creating")
}
if (moving) {
var dx = - clamp( mag_x(c,d), b[0] - canvas.w + 1, a[0] )
var dy = - clamp( mag_y(c,d), b[1] - canvas.h + 1, a[1] )
a[0] += dx
a[1] += dy
b[0] += dx
b[1] += dy
undo.new()
undo.save_rect(a[0], a[1], b[0] - a[0] + 1, b[1] - a[1] + 1)
blit.copy_to( canvas, selection_canvas, a[0], a[1] )
}
if (copying) {
}
creating = moving = copying = false
selector_el.classList.remove("dragging")
}
function show () {
selecting = true
}
function hide () {
reset()
selector_el.style.top = "-9999px"
selector_el.style.left = "-9999px"
selector_el.style.width = "0px"
selector_el.style.height = "0px"
creating = moving = copying = false
selection.hidden = true
selecting = false
}
var selection = {}
selection.reposition = reposition
selection.down = down
selection.move = move
selection.up = up
selection.canvas = selection_canvas
selection.show = show
selection.hide = hide
selection.hidden = true
return selection
})()

View File

@ -1,170 +0,0 @@
var Tool = Model({
init: function (el) {
this.el = el
this.lex = new Lex (el)
this.name = el.innerHTML
},
bind: function(){
var tool = this
tool.el.addEventListener('mousedown', function(e){
tool.focus()
})
tool.el.addEventListener('contextmenu', function(e){
tool.context(e)
})
if (tool.memorable) {
// console.log(tool.name, localStorage.getItem("ascii.tools." + tool.name) )
tool.use( localStorage.getItem("ascii.tools." + tool.name) == "true" )
}
},
use: function(){},
context: function(e){},
done: function(){},
focus: function(){
// focused && focused.blur()
current_tool && current_tool.blur()
current_tool = this
this.el.classList.add('focused')
this.use()
cursor_input.focus()
},
blur: function(){
current_tool = null
this.el.classList.remove('focused')
this.done()
}
})
var FileTool = Tool.extend({
focus: function(){
if (current_filetool === this) {
this.blur()
return
}
current_filetool && current_filetool.blur()
current_filetool = this
this.el.classList.add('focused')
this.use()
cursor_input.focus()
},
blur: function(){
current_filetool = null
this.el.classList.remove('focused')
this.done()
}
})
var RadioItem = Tool.extend({
init: function(group, el){
this.group = group
this.el = el
},
focus: function(){
this.el.classList.add('focused')
},
blur: function(){
this.el.classList.remove('focused')
},
bind: function(){
var control = this
this.el.addEventListener('mousedown', function(){
control.group.use(control)
})
}
})
var RadioGroup = Tool.extend({
init: function(el){
this.el = el
this.controls = {}
var names = el.innerHTML.split(' ')
el.innerHTML = ''
var group = this
names.forEach(function(value){
var el = document.createElement('span')
el.classList.add('radio','tool')
var control = new RadioItem(group, el)
if (value.substr(0,1) === '*') {
control.value = value = value.substr(1)
group.use(control)
}
control.value = el.innerHTML = value
group.controls[value] = control
group.el.appendChild(el)
})
},
use: function(control){
if (typeof control === 'string') {
control = this.controls[control]
}
this.selected_control && this.selected_control.blur()
this.value = control.value
this.selected_control = control
control.focus()
control.use()
if (this.memorable){
localStorage.setItem("ascii.tools." + this.name, this.value)
}
},
bind: function(){
var tool = this
for (var n in this.controls){
this.controls[n].bind()
}
if (tool.memorable) {
var value = localStorage.getItem("ascii.tools." + tool.name)
if (value) tool.use(value)
}
}
})
var Checkbox = Tool.extend({
init: function (el){
this.__init(el)
var name = this.name.replace(/^[x_] /,"")
var state = localStorage.getItem("ascii.tools." + name) == "true" || this.name[0] == "x"
this.name = name
this.update(state)
},
update: function(state){
if (state) this.el.innerHTML = "x " + this.name
else this.el.innerHTML = "_ " + this.name
if (this.memorable) { localStorage.setItem("ascii.tools." + this.name, !! state) }
}
})
var BlurredCheckbox = Checkbox.extend({
focus: function(){
this.use()
},
blur: function(){
this.el.classList.remove('focused')
this.done()
}
})
var BlurredTool = Tool.extend({
focus: function(){
this.use()
},
blur: function(){
this.el.classList.remove('focused')
this.done()
}
})
var HiddenCheckbox = BlurredCheckbox.extend({
on: "o",
off: ".",
init: function (el){
this.el = el
this.lex = new Lex (el)
this.name = this.el.id
var state = localStorage.getItem("ascii.tools." + name) == "true" || this.el.innerHTML[0] == this.on
this.update(state)
},
update: function(state){
this.el.innerHTML = state ? this.on : this.off
if (this.memorable) { localStorage.setItem("ascii.tools." + this.name, !! state) }
}
})

View File

@ -1,176 +0,0 @@
var transform = (function(){
var p = [0,0], q = [0,0]
var mode
var copy
function down (e, lex, point){
p[0] = point[0]
p[1] = point[1]
q[0] = e.pageX
q[1] = e.pageY
undo.new()
undo.save_rect(0, 0, canvas.w, canvas.h)
copy = canvas.clone()
mode.init(e)
}
function move (e, lex, point){
var pdx = point[0] - p[0]
var pdy = point[1] - p[1]
var dx = e.pageX - q[0]
var dy = e.pageY - q[1]
var w = canvas.w
var h = canvas.h
mode.before(dx, dy, pdx, pdy, point)
for (var x = 0; x < w; x++) {
for (var y = 0; y < h; y++) {
lex = canvas.get(x, y)
if (! mode.shade( copy, canvas, lex, x, y, w, h )) {
lex.build()
}
}
}
}
function up (e){
}
var modes = {
rotate: {
init: function(e){
mode.theta = 0
},
before: function(dx, dy){
var radius = dist(0, 0, dx, dy)
if (radius < 10) return
mode.theta = angle(0, 0, dx, -dy)
},
shade: function(src, dest, lex, x, y, w, h){
x = (x/w) * 2 - 1
y = (y/h) * 2 - 1
var ca = cos(mode.theta)
var sa = sin(mode.theta)
var a = x * ca - y * sa
var b = x * sa + y * ca
x = (a + 1) / 2 * w
y = (b + 1) / 2 * h
var copy = src.get(x, y)
lex.assign(copy)
return true
},
},
scale: {
init: function(e){
mode.independent = e.shiftKey || e.altKey || e.metaKey
mode.x_scale = mode.y_scale = 0
},
before: function(dx, dy, pdx, pdy){
if (mode.independent) {
mode.x_scale = Math.pow(2, -pdx / (canvas.w / 8))
mode.y_scale = Math.pow(2, -pdy / (canvas.h / 8))
}
else {
mode.x_scale = mode.y_scale = Math.pow(2, -pdx / (canvas.w / 8))
}
},
shade: function(src, dest, lex, x, y, w, h){
x = ((x-p[0])/w) * 2 - 1
y = ((y-p[1])/h) * 2 - 1
x *= mode.x_scale
y *= mode.y_scale
x = (x + 1) / 2 * w
y = (y + 1) / 2 * h
var copy = src.get(x+p[0], y+p[1])
lex.assign(copy)
return true
},
},
translate: {
init: function(e){
mode.dx = mode.dy = 0
},
before: function(dx, dy, pdx, pdy){
mode.dx = -pdx
mode.dy = -pdy
},
shade: function(src, dest, lex, x, y, w, h){
var copy = src.get(x+mode.dx, y+mode.dy)
lex.assign(copy)
return true
},
},
slice: {
init: function(e){
mode.is_y = ! (e.altKey || e.metaKey)
mode.reverse = !! (e.shiftKey)
mode.position = 0
mode.direction = 0
mode.last_dd = -1
},
before: function(dx, dy, pdx, pdy, point){
var new_position = mode.is_y ? point[1] : point[0]
var dd = mode.is_y ? pdx : pdy
if (mode.position !== new_position) {
mode.position = new_position
mode.direction = 0
}
if (mode.last_dd !== -1) {
mode.direction = mode.last_dd - dd
}
console.log(mode.position)
mode.last_dd = dd
copy.assign(canvas)
},
shade: function(src, dest, lex, x, y, w, h){
if (mode.is_y) {
if (y >= mode.position || (mode.reverse && mode.position >= y)) {
var copy = src.get(x + mode.direction, y)
lex.assign(copy)
}
}
else if (x >= mode.position || (mode.reverse && mode.position >= x)) {
var copy = src.get(x, y + mode.direction)
lex.assign(copy)
}
return true
},
},
/*
mode: {
init: function(e){
},
before: function(dx, dy, pdx, pdy){
},
shade: function(src, dest, lex, x, y, w, h){
},
},
*/
}
function set_mode(m){
if (m in modes) {
mode = modes[m]
transforming = true
}
}
function done(){
transforming = false
copy && copy.demolish()
}
return {
down: down,
move: move,
up: up,
set_mode: set_mode,
modes: modes,
done: done,
}
})()

View File

@ -1,203 +0,0 @@
var unicode = (function(){
var UNICODE_BLOCK_LIST = [
0x0020, 0x007F, "Basic Latin",
0x0080, 0x00FF, "Latin-1 Supplement",
0x2500, 0x257F, "Box Drawing",
0x2580, 0x259F, "Block Elements",
]
var UNICODE_BLOCK_COUNT = UNICODE_BLOCK_LIST.length / 3
var UNICODE_LOOKUP = {}
for (var i = 0, len = UNICODE_BLOCK_LIST.length; i < len; i += 3) {
UNICODE_LOOKUP[ UNICODE_BLOCK_LIST[i+2] ] = [ UNICODE_BLOCK_LIST[i], UNICODE_BLOCK_LIST[i+1] ]
}
function block (name, n){
var b = UNICODE_LOOKUP[name]
if (! b) return ""
return range.apply(null, b).map(function(n){ return String.fromCharCode(n) })
}
function entities (a) {
return a.map(function(k){ return "&#" + k.join(";&#") + ";" }).join("<br>")
}
function index (j) {
return [ UNICODE_BLOCK_LIST[j*3], UNICODE_BLOCK_LIST[j*3+1], UNICODE_BLOCK_LIST[j*3+2], [] ]
}
function range(m,n){
if (m > n) return []
var a = new Array (n-m)
for (var i = 0, j = m; j <= n; i++, j++) {
a[i] = j
}
return a
}
// [ 0xE3, 0x81, 0x82, 0xE3, 0x81, 0x84 ] => '\xE3\x81\x82\xE3\x81\x84'
// [ 0343, 0201, 0202, 0343, 0201, 0204 ] => '\343\201\202\343\201\204'
function convertBytesToEscapedString(data_bytes, base) {
var escaped = '';
for (var i = 0; i < data_bytes.length; ++i) {
var prefix = (base == 16 ? "\\x" : "\\");
var num_digits = base == 16 ? 2 : 3;
var escaped_byte = prefix + formatNumber(data_bytes[i], base, num_digits)
escaped += escaped_byte;
}
return escaped;
}
// r'\xE3\x81\x82\xE3\x81\x84' => [ 0xE3, 0x81, 0x82, 0xE3, 0x81, 0x84 ]
// r'\343\201\202\343\201\204' => [ 0343, 0201, 0202, 0343, 0201, 0204 ]
function convertEscapedBytesToBytes(str) {
var parts = str.split("\\x");
parts.shift(); // Trim the first element.
var codes = [];
var max = Math.pow(2, 8);
for (var i = 0; i < parts.length; ++i) {
var code = parseInt(parts[i], 16);
if (code >= 0 && code < max) {
codes.push(code);
} else {
// Malformed code ignored.
}
}
return codes;
}
// [ 0x3042, 0x3044 ] => "あい"
function convertUnicodeCodePointsToString(unicode_codes) {
var utf16_codes = convertUnicodeCodePointsToUtf16Codes(unicode_codes);
return convertUtf16CodesToString(utf16_codes);
}
// 0x3042 => [ 0xE3, 0x81, 0x82 ]
function convertUnicodeCodePointToUtf8Bytes(unicode_code) {
var utf8_bytes = [];
if (unicode_code < 0x80) { // 1-byte
utf8_bytes.push(unicode_code);
} else if (unicode_code < (1 << 11)) { // 2-byte
utf8_bytes.push((unicode_code >>> 6) | 0xC0);
utf8_bytes.push((unicode_code & 0x3F) | 0x80);
} else if (unicode_code < (1 << 16)) { // 3-byte
utf8_bytes.push((unicode_code >>> 12) | 0xE0);
utf8_bytes.push(((unicode_code >> 6) & 0x3f) | 0x80);
utf8_bytes.push((unicode_code & 0x3F) | 0x80);
} else if (unicode_code < (1 << 21)) { // 4-byte
utf8_bytes.push((unicode_code >>> 18) | 0xF0);
utf8_bytes.push(((unicode_code >> 12) & 0x3F) | 0x80);
utf8_bytes.push(((unicode_code >> 6) & 0x3F) | 0x80);
utf8_bytes.push((unicode_code & 0x3F) | 0x80);
}
return utf8_bytes;
}
// [ 0x3042, 0x3044 ] => [ 0x3042, 0x3044 ]
// [ 0xD840, 0xDC0B ] => [ 0x2000B ] // A surrogate pair.
function convertUnicodeCodePointsToUtf16Codes(unicode_codes) {
var utf16_codes = [];
for (var i = 0; i < unicode_codes.length; ++i) {
var unicode_code = unicode_codes[i];
if (unicode_code < (1 << 16)) {
utf16_codes.push(unicode_code);
} else {
var first = ((unicode_code - (1 << 16)) / (1 << 10)) + 0xD800;
var second = (unicode_code % (1 << 10)) + 0xDC00;
utf16_codes.push(first)
utf16_codes.push(second)
}
}
return utf16_codes;
}
// [ 0xE3, 0x81, 0x82, 0xE3, 0x81, 0x84 ] => [ 0x3042, 0x3044 ]
function convertUtf8BytesToUnicodeCodePoints(utf8_bytes) {
var unicode_codes = [];
var unicode_code = 0;
var num_followed = 0;
for (var i = 0; i < utf8_bytes.length; ++i) {
var utf8_byte = utf8_bytes[i];
if (utf8_byte >= 0x100) {
// Malformed utf8 byte ignored.
} else if ((utf8_byte & 0xC0) == 0x80) {
if (num_followed > 0) {
unicode_code = (unicode_code << 6) | (utf8_byte & 0x3f);
num_followed -= 1;
} else {
// Malformed UTF-8 sequence ignored.
}
} else {
if (num_followed == 0) {
unicode_codes.push(unicode_code);
} else {
// Malformed UTF-8 sequence ignored.
}
if (utf8_byte < 0x80){ // 1-byte
unicode_code = utf8_byte;
num_followed = 0;
} else if ((utf8_byte & 0xE0) == 0xC0) { // 2-byte
unicode_code = utf8_byte & 0x1f;
num_followed = 1;
} else if ((utf8_byte & 0xF0) == 0xE0) { // 3-byte
unicode_code = utf8_byte & 0x0f;
num_followed = 2;
} else if ((utf8_byte & 0xF8) == 0xF0) { // 4-byte
unicode_code = utf8_byte & 0x07;
num_followed = 3;
} else {
// Malformed UTF-8 sequence ignored.
}
}
}
if (num_followed == 0) {
unicode_codes.push(unicode_code);
} else {
// Malformed UTF-8 sequence ignored.
}
unicode_codes.shift(); // Trim the first element.
return unicode_codes;
}
// [ 0x3042, 0x3044 ] => "あい"
function convertUtf16CodesToString(utf16_codes) {
var unescaped = '';
for (var i = 0; i < utf16_codes.length; ++i) {
unescaped += String.fromCharCode(utf16_codes[i]);
}
return unescaped;
}
// 0xff => "ff"
// 0xff => "377"
function formatNumber(number, base, num_digits) {
var str = number.toString(base).toUpperCase();
for (var i = str.length; i < num_digits; ++i) {
str = "0" + str;
}
return str;
}
// encodes unicode characters as escaped bytes - \xFF
// encodes ONLY non-ascii characters
function escapeToEscapedBytes (txt) {
var escaped_txt = "", kode, utf8_bytes
for (var i = 0; i < txt.length; i++) {
kode = txt.charCodeAt(i)
if (kode > 0x7f) {
utf8_bytes = convertUnicodeCodePointToUtf8Bytes(kode)
escaped_txt += convertBytesToEscapedString(utf8_bytes, 16)
}
else {
escaped_txt += txt[i]
}
}
return escaped_txt
}
// convert \xFF\xFF\xFF to unicode
function unescapeFromEscapedBytes (str) {
var data_bytes = convertEscapedBytesToBytes(str);
var unicode_codes = convertUtf8BytesToUnicodeCodePoints(data_bytes);
return convertUnicodeCodePointsToString(unicode_codes);
}
return {
raw: UNICODE_BLOCK_LIST,
lookup: UNICODE_LOOKUP,
index: index,
range: range,
block: block,
escapeToEscapedBytes: escapeToEscapedBytes,
unescapeFromEscapedBytes: unescapeFromEscapedBytes,
}
})()

View File

@ -1,192 +0,0 @@
if (window.$) {
$.fn.int = function(){ return parseInt($(this).val(),10) }
$.fn.float = function(){ return parseFloat($(this).val()) }
$.fn.string = function(){ return trim($(this).val()) }
$.fn.enable = function() { return $(this).attr("disabled",null) }
$.fn.disable = function() { return $(this).attr("disabled","disabled") }
}
function noop(){}
function trim(s){ return s.replace(/^\s+/,"").replace(/\s+$/,"") }
var E = Math.E
var PI = Math.PI
var PHI = (1+Math.sqrt(5))/2
var TWO_PI = PI*2
var LN10 = Math.LN10
function clamp(n,a,b){ return n<a?a:n<b?n:b }
function norm(n,a,b){ return (n-a) / (b-a) }
function lerp(n,a,b){ return (b-a)*n+a }
function mix(n,a,b){ return a*(1-n)+b*n }
function ceil(n){ return Math.ceil(n) }
function floor(n){ return Math.floor(n) }
function round(n){ return Math.round(n) }
function max(a,b){ return Math.max(a,b) }
function min(a,b){ return Math.min(a,b) }
function abs(n){ return Math.abs(n) }
function sign(n){ return Math.abs(n)/n }
function pow(n,b) { return Math.pow(n,b) }
function exp(n) { return Math.exp(n) }
function log(n){ return Math.log(n) }
function ln(n){ return Math.log(n)/LN10 }
function sqrt(n) { return Math.sqrt(n) }
function cos(n){ return Math.cos(n) }
function sin(n){ return Math.sin(n) }
function tan(n){ return Math.tan(n) }
function acos(n){ return Math.cos(n) }
function asin(n){ return Math.sin(n) }
function atan(n){ return Math.atan(n) }
function atan2(a,b){ return Math.atan2(a,b) }
function sec(n){ return 1/cos(n) }
function csc(n){ return 1/sin(n) }
function cot(n){ return 1/tan(n) }
function cosp(n){ return (1+Math.cos(n))/2 } // cos^2
function sinp(n){ return (1+Math.sin(n))/2 }
function random(){ return Math.random() }
function rand(n){ return (Math.random()*n) }
function randint(n){ return rand(n)|0 }
function randrange(a,b){ return a + rand(b-a) }
function randsign(){ return random() >= 0.5 ? -1 : 1 }
function randnullsign(){ var r = random(); return r < 0.333 ? -1 : r < 0.666 ? 0 : 1 }
function xrandom(exp){ return Math.pow(Math.random(), exp) }
function xrand(exp,n){ return (xrandom(exp)*n) }
function xrandint(exp,n){ return rand(exp,n)|0 }
function xrandrange(exp,a,b){ return a + xrand(exp,b-a) }
function choice(a){ return a[randint(a.length)] }
function deg(n){ return n*180/PI }
function rad(n){ return n*PI/180 }
function xor(a,b){ a=!!a; b=!!b; return (a||b) && !(a&&b) }
function mod(n,m){ n = n % m; return n < 0 ? (m + n) : n }
function modi(n,m){ return floor(mod(n,m)) }
function dist(x0,y0,x1,y1){ return sqrt(pow(x1-x0,2)+pow(y1-y0,2)) }
function angle(x0,y0,x1,y1){ return atan2(y1-y0,x1-x0) }
function avg(m,n,a){ return (m*(a-1)+n)/a }
function quantize(a,b){ return floor(a/b)*b }
function quantile(a,b){ return floor(a/b) }
function pixel(x,y){ return 4*(mod(y,actual_h)*actual_w+mod(x,actual_w)) }
function rgbpixel(d,x,y){
var p = pixel(~~x,~~y)
r = d[p]
g = d[p+1]
b = d[p+2]
a = d[p+3]
}
function fit(d,x,y){ rgbpixel(d,x*actual_w/w,y*actual_h/h) }
function step(a, b){
return (b >= a) + 0
// ^^ bool -> int
}
function julestep (a,b,n) {
return clamp(norm(n,a,b), 0.0, 1.0);
}
// hermite curve apparently
function smoothstep(min,max,n){
var t = clamp((n - min) / (max - min), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t)
}
function toArray(a){ return Array.prototype.slice.call(a) }
function shuffle(a){
for (var i = a.length; i > 0; i--){
var r = randint(i)
var swap = a[i-1]
a[i-1] = a[r]
a[r] = swap
}
return a
}
function reverse(a){
var reversed = []
for (var i = 0, _len = a.length-1; i <= _len; i++){
reversed[i] = a[_len-i]
}
return reversed
}
function deinterlace(a){
var odd = [], even = []
for (var i = 0, _len = a.length; i < _len; i++) {
if (i % 2) even.push(a[i])
else odd.push(a[i])
}
return [even, odd]
}
function weave(a){
var aa = deinterlace(a)
var b = []
aa[0].forEach(function(el){ b.push(el) })
reverse(aa[1]).forEach(function(el){ b.push(el) })
return b
}
function cssRule (selector, declaration) {
var x = document.styleSheets, y = x.length-1;
x[y].insertRule(selector+"{"+declaration+"}", x[y].cssRules.length);
}
// easing functions
function circular (t) { return Math.sqrt( 1 - ( --t * t ) ) }
function quadratic (t) { return t * ( 2 - t ) }
function back (t) {
var b = 4;
return ( t = t - 1 ) * t * ( ( b + 1 ) * t + b ) + 1;
}
function bounce (t) {
if (t >= 1) return 1;
if ( ( t /= 1 ) < ( 1 / 2.75 ) ) {
return 7.5625 * t * t;
} else if ( t < ( 2 / 2.75 ) ) {
return 7.5625 * ( t -= ( 1.5 / 2.75 ) ) * t + 0.75;
} else if ( t < ( 2.5 / 2.75 ) ) {
return 7.5625 * ( t -= ( 2.25 / 2.75 ) ) * t + 0.9375;
} else {
return 7.5625 * ( t -= ( 2.625 / 2.75 ) ) * t + 0.984375;
}
}
function elastic (t) {
var f = 0.22,
e = 0.4;
if ( t === 0 ) { return 0; }
if ( t == 1 ) { return 1; }
return ( e * Math.pow( 2, - 10 * t ) * Math.sin( ( t - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
}
Model=function a(b,c,d,e){function f(){var a=this,f={};a.on=function(a,b){(f[a]||
(f[a]=[])).push(b)},a.trigger=function(a,b){for(var c=f[a],d=0;c&&d<c.length;)c
[d++](b)},a.off=function(a,b){for(d=f[a]||[];b&&(c=d.indexOf(b))>-1;)d.splice(c
,1);f[a]=b?d:[]};for(c in b)d=b[c],a[c]=typeof d=="function"?function(){return(
d=this.apply(a,arguments))===e?a:d}.bind(d):d;a.init&&a.init.apply(a,arguments)
}return f.extend=function(f){d={};for(c in b)d[c]=b[c];for(c in f)d[c]=f[c],b[c
]!==e&&(d["__"+c]=b[c]);return a(d)},f},typeof module=="object"&&(module.exports
=Model); // c-{{{-<
function defaults (dest, src) {
dest = dest || {}
for (var i in src) {
dest[i] = typeof dest[i] == 'undefined' ? src[i] : dest[i]
}
return dest
}
function setSelectionRange(input, selectionStart, selectionEnd) {
if (input.setSelectionRange) {
input.focus();
input.setSelectionRange(selectionStart, selectionEnd);
}
else if (input.createTextRange) {
var range = input.createTextRange();
range.collapse(true);
range.moveEnd('character', selectionEnd);
range.moveStart('character', selectionStart);
range.select();
}
}
function setCaretToPos(input, pos) {
setSelectionRange(input, pos, pos);
}

View File

@ -1,121 +0,0 @@
#!/bin/sh
#
PACKAGE_NAME="MiRCART-nw";
RELEASE_DEPS="cpio find gunzip rm sed tar unzip wget zip";
NWJS_MANIFEST_FNAME="nwjs.manifest";
NWJS_PLATFORMS="linux-ia32 linux-x64 win-ia32 win-x64";
NWJS_VERSION="0.34.5";
NWJS_SUBDIR="nwjs-v${NWJS_VERSION}-%NWJS_PLATFORM%";
NWJS_URL_linux="https://dl.nwjs.io/v${NWJS_VERSION}/nwjs-v${NWJS_VERSION}-%NWJS_PLATFORM%.tar.gz";
NWJS_URL_win="https://dl.nwjs.io/v${NWJS_VERSION}/nwjs-v${NWJS_VERSION}-%NWJS_PLATFORM%.zip";
RELEASES_DNAME="releases";
extract() {
local _fname="${1}" _dest_dname="${2}";
if [ -n "${_fname}" -a -z "${_fname##*.tar.gz}" ]; then
tar -C "${_dest_dname}" -xpf "${_fname}";
elif [ -n "${_fname}" -a -z "${_fname##*.zip}" ]; then
unzip -d "${_dest_dname}" "${_fname}";
else
echo "error: file \`${_fname}' is of unknown archive type" >&2; exit 1;
fi;
};
msgf() {
local _fmt="${1}"; shift;
printf "%s >>> ${_fmt}\n" "$(date +"%d-%^b-%Y %H:%M:%S")" "${@}";
};
subst() {
local _string="${1}" _search="${2}" _replace="${3}" _string_="";
_string_="${_string%${_search}*}";
_string_="${_string_}${_replace}"
_string_="${_string_}${_string#*${_search}}";
echo "${_string_}";
};
deploy() {
local _platform="${1}" _vflag="${2}" _nwjs_fname="" _nwjs_subdir="" _nwjs_url="" \
_release_fname="" _release_dname="" _release_version="";
_nwjs_subdir="$(subst "${NWJS_SUBDIR}" "%NWJS_PLATFORM%" "${_platform}")";
_nwjs_url="$(subst "$(eval echo \"\${NWJS_URL_${_platform%%-*}}\")" "%NWJS_PLATFORM%" "${_platform}")";
_nwjs_fname="${RELEASES_DNAME}/${_nwjs_url##*/}";
_release_version="$(sed -n '/^\s*"version":/s/^.*:\s*"\([0-9.]\+\)",\?\s*$/\1/p' package.json)";
_release_dname="${RELEASES_DNAME}/${PACKAGE_NAME}-release-${_platform}-${_release_version}";
_release_fname="${_release_dname}.zip";
trap "rm -fr ${_release_dname}" EXIT HUP INT QUIT PIPE TERM USR1 USR2;
if [ "${_vflag:-0}" -eq 0 ]; then
wget -cqO "${_nwjs_fname}" "${_nwjs_url}";
else
wget -cO "${_nwjs_fname}" "${_nwjs_url}";
fi;
if ! sha256sum --ignore-missing -c --status "${NWJS_MANIFEST_FNAME}"; then
echo "error: SHA256 sum mismatch for \`${_nwjs_fname}'" >&2; return 1;
fi;
rm -rf "${_release_dname}"; mkdir -p "${_release_dname}"; extract "${_nwjs_fname}" "${_release_dname}";
cd "${_release_dname}/${_nwjs_subdir}";
find . \
-mindepth 1 |\
cpio --quiet -dmp ..;
cd "${OLDPWD}";
rm -fr "${_release_dname}/${_nwjs_subdir}";
find -L . \
-mindepth 1 \
-not -path "./${RELEASES_DNAME}/*" \
-not -path "./${RELEASES_DNAME}" \
-not -name '*.sw*' \
-not -name "${0##*/}" \
-not -name "${NWJS_MANIFEST_FNAME}" |\
cpio --quiet -dLmp "${_release_dname}";
cd "${RELEASES_DNAME}";
if [ "${_vflag:-0}" -eq 0 ]; then
zip -9 -r "${_release_fname##${RELEASES_DNAME}/}" "${_release_dname##${RELEASES_DNAME}/}" >/dev/null;
else
zip -9 -r "${_release_fname##${RELEASES_DNAME}/}" "${_release_dname##${RELEASES_DNAME}/}";
fi;
cd "${OLDPWD}"; rm -fr "${_release_dname}";
trap - EXIT HUP INT QUIT PIPE TERM USR1 USR2;
};
usage() {
echo "usage: ${0} [-h] [-v] [platform...]" >&2;
echo " -h.........: show this screen" >&2;
echo " -v.........: be verbose" >&2;
echo " platform...: one of: \`${NWJS_PLATFORMS}'" >&2;
};
main() {
local _cmd="" _opt="" _platform="" _platforms="" _vflag=0;
while getopts hv _opt; do
case "${_opt}" in
h) usage; exit 0; ;;
v) _vflag=1; ;;
*) usage; exit 1; ;;
esac; done;
shift $((${OPTIND}-1));
for _cmd in ${RELEASE_DEPS}; do
if ! which "${_cmd}" >/dev/null; then
echo "error: missing prerequisite command \`${_cmd}'";
exit 1;
fi;
done;
_platforms="${@}"; mkdir -p "${RELEASES_DNAME}";
for _platform in ${_platforms:-${NWJS_PLATFORMS}}; do
msgf "Building ${_platform} release...";
if [ "${_vflag:-0}" -eq 0 ]; then
deploy "${_platform}" "${_vflag}" >/dev/null;
else
deploy "${_platform}" "${_vflag}";
fi;
msgf "Built ${_platform} release.";
done;
};
set -o errexit -o noglob;
main "${@}";
# vim:foldmethod=marker sw=8 ts=8 tw=120

View File

@ -1,28 +0,0 @@
Jollo LNT license
Version 1 - February 2015
Copyright, 2015. JOLLO NET NA.
The Jollo IRC Network. <//jollo.org/>
Vu, fare wanderer, confronted with raw, programmatic instruction
dans la forme la plus pure. A hesitation, troubled to the terms
qui ce license affirme. Par un voyage du explorer le mechanisme
et ponder la fabrication. Voila! La remide: egress sans risque.
Sans trace (Leave No Trace) via sept principales:
0. Modifique language en advance. L'Apposer Jollo LNT license
with copies en distribuer.
1. Non responsible pour neglige programme du problematique.
2. Non sympathie pour neglige programme du problematique.
3. Non permission l'modifique under any circumstance.
4. Non permission distribution under any circumstance.
5. Respect les programmatic instructions.
6. Non interfere avec l'harmonie d'une amitie.

View File

@ -1,15 +1,19 @@
## MiRCART-{cordoba,nw,www} -- mIRC art editor for {Android,{Linux,Windows},browsers} (WIP)
Originally based on [[1](#r1)].
# MiRCART.py -- mIRC art editor for Windows & Linux (WIP)
* Prerequisites on Windows: install Python v3.6.x[1] and script dependencies w/ the following elevated command prompt command line:
`pip install requests urllib3 wxPython`
* Prerequisites on Linux: python3 && python-wx{gtk2.8,tools} on Debian-family Linux distributions
* Screenshot:
![Screenshot](https://github.com/lalbornoz/MiRCARTools/raw/master/assets/images/MiRCART.png "Screenshot")
## IrcMiRCARTBot.py -- IRC<->MiRC2png bot (for EFnet #MiRCART) (pending cleanup)
# IrcMiRCARTBot.py -- IRC<->MiRC2png bot (for EFnet #MiRCART) (pending cleanup)
* Prerequisites: python3 && python3-{json,requests,urllib3} on Debian-family Linux distributions
* IrcMiRCARTBot.py usage: IrcMiRCARTBot.py `<IRC server hostname>` [`<IRC server port; defaults to 6667>`] [`<IRC bot nick name; defaults to pngbot>`] [`<IRC bot user name; defaults to pngbot>`] [`<IRC bot real name; defaults to pngbot>`] [`<IRC bot channel name; defaults to #MiRCART>`]
## MiRCARTToPngFile.py -- convert ASCII w/ mIRC control codes to monospaced PNG (pending cleanup)
# MiRCARTToPngFile.py -- convert ASCII w/ mIRC control codes to monospaced PNG (pending cleanup)
* Prerequisites: python3 && python3-pil on Debian-family Linux distributions
* MiRC2png.py usage: MiRC2png.py `<MiRCART input file pathname>` `<PNG image output file pathname>` [`<Font file pathname; defaults to DejaVuSansMono.ttf>`] [`<Font size; defaults to 11>`]
## References
``Fri, 05 Jan 2018 17:01:47 +0100 [1]`` <a href="https://asdf.us/asciiblaster" id="r1">asciiblaster</a>
References:
Fri, 05 Jan 2018 17:01:47 +0100 [1] Python Releases for Windows | Python.org <https://www.python.org/downloads/windows/>
vim:tw=0

View File

@ -1,21 +0,0 @@
1) feature: animation; Blender mIRCart Python importer plugin
2) feature: {bold,italic,underline} attributes
3) feature: comic editor/generator *
4) feature: draw w/ keyboard instead of [LR]MB
5) feature: {line,measuring} tool
6) feature: multiplayer realtime editing
7) feature: status bar w/ position, etc.
8) feature: zoom {in,out} (esp. on Android)
9) reimplement: ANSI (maybe,) {save,upload} as PNG & gallery, cutoff (print line #(s) affected, tunably,) shaders (maybe)
10) releases: provide signed release APK
In progress:
1) each newly created & modified(!) ascii is assigned an ascii UUID, if not present already
2) each ascii w/ an ascii UUID is auto-saved to localStorage every 3 minutes
3) ascii autosaves w/ count >8 (or >8*3mins=24mins old) are purged from localStorage
4) asciis w/ count >8 are purged from localStorage
5) limits are tunable and either defaulted or localStorage'd
6) UI lists: a) asciis (with UUID) b) autosaves c) parameters
7) always prompt on close window/exit/...
8) always prompt on new
9) save to text file @ standalone app

203
libcanvas/MiRCARTCanvas.py Normal file
View File

@ -0,0 +1,203 @@
#!/usr/bin/env python3
#
# MiRCARTCanvas.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
from MiRCARTCanvasBackend import MiRCARTCanvasBackend
from MiRCARTCanvasJournal import MiRCARTCanvasJournal
from MiRCARTCanvasExportStore import MiRCARTCanvasExportStore, haveMiRCARTToPngFile, haveUrllib
from MiRCARTCanvasImportStore import MiRCARTCanvasImportStore
from MiRCARTCanvasInterface import MiRCARTCanvasInterface
from MiRCARTImgurApiKey import MiRCARTImgurApiKey
import wx
class MiRCARTCanvas(wx.Panel):
"""XXX"""
parentFrame = None
defaultCanvasPos = defaultCanvasSize = defaultCellSize = None
canvasMap = canvasPos = canvasSize = None
brushColours = brushPos = brushSize = None
canvasBackend = canvasJournal = None
canvasExportStore = canvasImportStore = None
canvasInterface = None
imgurApiKey = MiRCARTImgurApiKey.imgurApiKey
# {{{ _commitPatch(self, patch): XXX
def _commitPatch(self, patch):
self.canvasMap[patch[1]][patch[0]] = patch[2:]
# }}}
# {{{ _dispatchDeltaPatches(self, deltaPatches): XXX
def _dispatchDeltaPatches(self, deltaPatches):
eventDc = self.canvasBackend.getDeviceContext(self)
for patch in deltaPatches:
if self.canvasBackend.drawPatch(eventDc, patch):
self._commitPatch(patch)
self.parentFrame.onCanvasUpdate(undoLevel=self.canvasJournal.patchesUndoLevel)
# }}}
# {{{ _dispatchPatch(self, eventDc, isCursor, patch): XXX
def _dispatchPatch(self, eventDc, isCursor, patch):
if not self._canvasDirtyCursor:
self.canvasBackend.drawCursorMaskWithJournal( \
self.canvasJournal, eventDc)
self._canvasDirtyCursor = True
if self.canvasBackend.drawPatch(eventDc, patch):
patchDeltaCell = self.canvasMap[patch[1]][patch[0]]
patchDelta = [*patch[0:2], *patchDeltaCell]
if isCursor:
self.canvasJournal.pushCursor(patchDelta)
else:
if not self._canvasDirty:
self.canvasJournal.pushDeltas([], [])
self._canvasDirty = True
self.canvasJournal.updateCurrentDeltas(patchDelta, patch)
self._commitPatch(patch)
# }}}
# {{{ onPanelClose(self, event): XXX
def onPanelClose(self, event):
self.Destroy()
# }}}
# {{{ onPanelEnterWindow(self, event): XXX
def onPanelEnterWindow(self, event):
self.parentFrame.SetFocus()
# }}}
# {{{ onPanelInput(self, event): XXX
def onPanelInput(self, event):
eventDc = self.canvasBackend.getDeviceContext(self)
eventType = event.GetEventType()
self._canvasDirty = self._canvasDirtyCursor = False
tool = self.canvasInterface.canvasTool
if eventType == wx.wxEVT_CHAR:
mapPoint = self.brushPos
doSkip = tool.onKeyboardEvent( \
event, mapPoint, self.brushColours, self.brushSize, \
chr(event.GetUnicodeKey()), self._dispatchPatch, eventDc)
if doSkip:
event.Skip(); return;
else:
mapPoint = self.canvasBackend.xlateEventPoint(event, eventDc)
if mapPoint[0] >= self.canvasSize[0] \
or mapPoint[1] >= self.canvasSize[1]:
return
self.brushPos = mapPoint
tool.onMouseEvent( \
event, mapPoint, self.brushColours, self.brushSize, \
event.Dragging(), event.LeftIsDown(), event.RightIsDown(), \
self._dispatchPatch, eventDc)
if self._canvasDirty:
self.parentFrame.onCanvasUpdate(cellPos=self.brushPos, \
undoLevel=self.canvasJournal.patchesUndoLevel)
if eventType == wx.wxEVT_MOTION:
self.parentFrame.onCanvasUpdate(cellPos=mapPoint)
# }}}
# {{{ onPanelLeaveWindow(self, event): XXX
def onPanelLeaveWindow(self, event):
eventDc = self.canvasBackend.getDeviceContext(self)
self.canvasBackend.drawCursorMaskWithJournal( \
self.canvasJournal, eventDc)
# }}}
# {{{ onPanelPaint(self, event): XXX
def onPanelPaint(self, event):
self.canvasBackend.onPanelPaintEvent(self, event)
# }}}
# {{{ onStoreUpdate(self, newCanvasSize, newCanvas=None): XXX
def onStoreUpdate(self, newCanvasSize, newCanvas=None):
self.resize(newCanvasSize=newCanvasSize)
eventDc = self.canvasBackend.getDeviceContext(self)
for numRow in range(self.canvasSize[1]):
for numCol in range(self.canvasSize[0]):
if newCanvas != None \
and numRow < len(newCanvas) \
and numCol < len(newCanvas[numRow]):
self._commitPatch([ \
numCol, numRow, *newCanvas[numRow][numCol]])
self.canvasBackend.drawPatch(eventDc, \
[numCol, numRow, \
*self.canvasMap[numRow][numCol]])
wx.SafeYield()
# }}}
# {{{ resize(self, newCanvasSize): XXX
def resize(self, newCanvasSize):
if newCanvasSize != self.canvasSize:
if self.canvasMap == None:
self.canvasMap = []; oldCanvasSize = [0, 0];
else:
oldCanvasSize = self.canvasSize
deltaCanvasSize = [b-a for a,b in zip(oldCanvasSize, newCanvasSize)]
newWinSize = [a*b for a,b in zip(newCanvasSize, self.canvasBackend.cellSize)]
self.SetMinSize(newWinSize)
self.SetSize(wx.DefaultCoord, wx.DefaultCoord, *newWinSize)
curWindow = self
while curWindow != None:
curWindow.Layout()
curWindow = curWindow.GetParent()
self.canvasBackend.resize(newCanvasSize, self.canvasBackend.cellSize)
eventDc = self.canvasBackend.getDeviceContext(self)
self.canvasJournal.resetCursor(); self.canvasJournal.resetUndo();
if deltaCanvasSize[0] < 0:
for numRow in range(oldCanvasSize[1]):
del self.canvasMap[numRow][-1:(deltaCanvasSize[0]-1):-1]
else:
for numRow in range(oldCanvasSize[1]):
self.canvasMap[numRow].extend( \
[[1, 1, 0, " "]] * deltaCanvasSize[0])
for numNewCol in range(oldCanvasSize[0], newCanvasSize[0]):
self.canvasBackend.drawPatch( \
eventDc, [numNewCol, numRow, \
*self.canvasMap[numRow][-1]])
if deltaCanvasSize[1] < 0:
del self.canvasMap[-1:(deltaCanvasSize[1]-1):-1]
else:
for numNewRow in range(oldCanvasSize[1], newCanvasSize[1]):
self.canvasMap.extend( \
[[[1, 1, 0, " "]] * newCanvasSize[0]])
for numNewCol in range(newCanvasSize[0]):
self.canvasBackend.drawPatch( \
eventDc, [numNewCol, numNewRow, \
*self.canvasMap[-1][-1]])
self.canvasSize = newCanvasSize
wx.SafeYield()
self.parentFrame.onCanvasUpdate(size=newCanvasSize, undoLevel=-1)
# }}}
# {{{ __del__(self): destructor method
def __del__(self):
if self.canvasMap != None:
self.canvasMap.clear(); self.canvasMap = None;
# }}}
#
# __init__(self, parent, parentFrame, defaultCanvasPos, defaultCanvasSize, defaultCellSize): initialisation method
def __init__(self, parent, parentFrame, defaultCanvasPos, defaultCanvasSize, defaultCellSize):
super().__init__(parent, pos=defaultCanvasPos, \
size=[w*h for w,h in zip(defaultCanvasSize, defaultCellSize)])
self.parentFrame = parentFrame
self.canvasMap = None
self.canvasPos = defaultCanvasPos; self.canvasSize = defaultCanvasSize;
self.defaultCanvasPos = defaultCanvasPos; self.defaultCanvasSize = defaultCanvasSize;
self.brushColours = [4, 1]; self.brushPos = [0, 0]; self.brushSize = [1, 1];
self.parentFrame.onCanvasUpdate( \
brushSize=self.brushSize, colours=self.brushColours)
self.canvasBackend = MiRCARTCanvasBackend(defaultCanvasSize, defaultCellSize)
self.canvasJournal = MiRCARTCanvasJournal()
self.canvasExportStore = MiRCARTCanvasExportStore(parentCanvas=self)
self.canvasImportStore = MiRCARTCanvasImportStore(parentCanvas=self)
self.canvasInterface = MiRCARTCanvasInterface(self, parentFrame)
# Bind event handlers
self.Bind(wx.EVT_CLOSE, self.onPanelClose)
self.Bind(wx.EVT_ENTER_WINDOW, self.onPanelEnterWindow)
self.Bind(wx.EVT_LEAVE_WINDOW, self.onPanelLeaveWindow)
self.parentFrame.Bind(wx.EVT_CHAR, self.onPanelInput)
for eventType in( \
wx.EVT_LEFT_DOWN, wx.EVT_MOTION, wx.EVT_RIGHT_DOWN):
self.Bind(eventType, self.onPanelInput)
self.Bind(wx.EVT_PAINT, self.onPanelPaint)
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,157 @@
#!/usr/bin/env python3
#
# MiRCARTCanvasBackend.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
from MiRCARTColours import MiRCARTColours
import wx
class MiRCARTCanvasBackend():
"""XXX"""
_font = _brushes = _pens = None
_lastBrush = _lastPen = None
canvasBitmap = cellSize = None
# {{{ _drawBrushPatch(self, eventDc, patch): XXX
def _drawBrushPatch(self, eventDc, patch):
absPoint = self._xlatePoint(patch)
brushFg = self._brushes[patch[3]]
brushBg = self._brushes[patch[2]]
pen = self._pens[patch[3]]
self._setBrushDc(brushBg, brushFg, eventDc, pen)
eventDc.DrawRectangle(*absPoint, *self.cellSize)
# }}}
# {{{ _drawCharPatch(self, eventDc, patch): XXX
def _drawCharPatch(self, eventDc, patch):
absPoint = self._xlatePoint(patch)
brushFg = self._brushes[patch[2]]
brushBg = self._brushes[patch[3]]
pen = self._pens[patch[3]]
fontBitmap = wx.Bitmap(*self.cellSize)
fontDc = wx.MemoryDC(); fontDc.SelectObject(fontBitmap);
fontDc.SetTextForeground(wx.Colour(MiRCARTColours[patch[2]][0:4]))
fontDc.SetTextBackground(wx.Colour(MiRCARTColours[patch[3]][0:4]))
fontDc.SetBrush(brushBg); fontDc.SetBackground(brushBg); fontDc.SetPen(pen);
fontDc.SetFont(self._font)
fontDc.DrawRectangle(0, 0, *self.cellSize)
fontDc.DrawText(patch[5], 0, 0)
eventDc.Blit(*absPoint, *self.cellSize, fontDc, 0, 0)
# }}}
# {{{ _finiBrushesAndPens(self): XXX
def _finiBrushesAndPens(self):
for brush in self._brushes or []:
brush.Destroy()
self._brushes = None
for pen in self._pens or []:
pen.Destroy()
self._pens = None
self._lastBrushBg = self._lastBrushFg = self._lastPen = None;
# }}}
# {{{ _initBrushesAndPens(self): XXX
def _initBrushesAndPens(self):
self._brushes = [None for x in range(len(MiRCARTColours))]
self._pens = [None for x in range(len(MiRCARTColours))]
for mircColour in range(len(MiRCARTColours)):
self._brushes[mircColour] = wx.Brush( \
wx.Colour(MiRCARTColours[mircColour][0:4]), wx.BRUSHSTYLE_SOLID)
self._pens[mircColour] = wx.Pen( \
wx.Colour(MiRCARTColours[mircColour][0:4]), 1)
self._lastBrushBg = self._lastBrushFg = self._lastPen = None;
# }}}
# {{{ _setBrushDc(self, brushBg, brushFg, dc, pen): XXX
def _setBrushDc(self, brushBg, brushFg, dc, pen):
if self._lastBrushBg != brushBg:
dc.SetBackground(brushBg)
self._lastBrushBg = brushBg
if self._lastBrushFg != brushFg:
dc.SetBrush(brushFg)
self._lastBrushFg = brushFg
if self._lastPen != pen:
dc.SetPen(pen)
self._lastPen = pen
# }}}
# {{{ _xlatePoint(self, patch): XXX
def _xlatePoint(self, patch):
return [a*b for a,b in zip(patch[0:2], self.cellSize)]
# }}}
# {{{ drawPatch(self, eventDc, patch): XXX
def drawPatch(self, eventDc, patch):
if patch[0] < self.canvasSize[0] \
and patch[0] >= 0 \
and patch[1] < self.canvasSize[1] \
and patch[1] >= 0:
if patch[5] == " ":
self._drawBrushPatch(eventDc, patch)
else:
self._drawCharPatch(eventDc, patch)
return True
else:
return False
# }}}
# {{{ drawCursorMaskWithJournal(self, canvasJournal, eventDc): XXX
def drawCursorMaskWithJournal(self, canvasJournal, eventDc):
for patch in canvasJournal.popCursor():
self.drawPatch(eventDc, patch)
# }}}
# {{{ getDeviceContext(self, parentWindow): XXX
def getDeviceContext(self, parentWindow):
eventDc = wx.BufferedDC( \
wx.ClientDC(parentWindow), self.canvasBitmap)
self._lastBrushBg = self._lastBrushFg = self._lastPen = None;
return eventDc
# }}}
# {{{ onPanelPaintEvent(self, panelWindow, panelEvent): XXX
def onPanelPaintEvent(self, panelWindow, panelEvent):
if self.canvasBitmap != None:
eventDc = wx.BufferedPaintDC(panelWindow, self.canvasBitmap)
# }}}
# {{{ reset(self, canvasSize, cellSize):
def reset(self, canvasSize, cellSize):
self.resize(canvasSize, cellSize)
# }}}
# {{{ resize(self, canvasSize, cellSize):
def resize(self, canvasSize, cellSize):
winSize = [a*b for a,b in zip(canvasSize, cellSize)]
if self.canvasBitmap == None:
self.canvasBitmap = wx.Bitmap(winSize)
else:
oldDc = wx.MemoryDC()
oldDc.SelectObject(self.canvasBitmap)
newDc = wx.MemoryDC()
newBitmap = wx.Bitmap(winSize)
newDc.SelectObject(newBitmap)
newDc.Blit(0, 0, *self.canvasBitmap.GetSize(), oldDc, 0, 0)
oldDc.SelectObject(wx.NullBitmap)
self.canvasBitmap.Destroy(); self.canvasBitmap = newBitmap;
self.canvasSize = canvasSize; self.cellSize = cellSize;
self._font = wx.Font( \
8, \
wx.FONTFAMILY_TELETYPE, \
wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
# }}}
# {{{ xlateEventPoint(self, event, eventDc): XXX
def xlateEventPoint(self, event, eventDc):
eventPoint = event.GetLogicalPosition(eventDc)
rectX = eventPoint.x - (eventPoint.x % self.cellSize[0])
rectY = eventPoint.y - (eventPoint.y % self.cellSize[1])
mapX = int(rectX / self.cellSize[0] if rectX else 0)
mapY = int(rectY / self.cellSize[1] if rectY else 0)
return (mapX, mapY)
# }}}
# {{{ __del__(self): destructor method
def __del__(self):
if self.canvasBitmap != None:
self.canvasBitmap.Destroy(); self.canvasBitmap = None;
self._finiBrushesAndPens()
# }}}
#
# __init__(self, canvasSize, cellSize): initialisation method
def __init__(self, canvasSize, cellSize):
self._initBrushesAndPens()
self.reset(canvasSize, cellSize)
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,111 @@
#!/usr/bin/env python3
#
# MiRCARTCanvasExportStore.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
import io, os, tempfile
try:
from MiRCARTToPngFile import MiRCARTToPngFile
haveMiRCARTToPngFile = True
except ImportError:
haveMiRCARTToPngFile = False
try:
import base64, json, requests, urllib.request
haveUrllib = True
except ImportError:
haveUrllib = False
class MiRCARTCanvasExportStore():
"""XXX"""
parentCanvas = None
# {{{ _exportFileToImgur(self, apiKey, imgName, imgTitle, pathName): upload single PNG file to Imgur
def _exportFileToImgur(self, apiKey, imgName, imgTitle, pathName):
with open(pathName, "rb") as requestImage:
requestImageData = requestImage.read()
requestData = { \
"image": base64.b64encode(requestImageData), \
"key": apiKey, \
"name": imgName, \
"title": imgTitle, \
"type": "base64"}
requestHeaders = {"Authorization": "Client-ID " + apiKey}
responseHttp = requests.post( \
"https://api.imgur.com/3/upload.json", \
data=requestData, headers=requestHeaders)
responseDict = json.loads(responseHttp.text)
if responseHttp.status_code == 200:
return [200, responseDict.get("data").get("link")]
else:
return [responseHttp.status_code, ""]
# }}}
# {{{ exportBitmapToPngFile(self, canvasBitmap, outPathName, outType): XXX
def exportBitmapToPngFile(self, canvasBitmap, outPathName, outType):
return canvasBitmap.ConvertToImage().SaveFile(outPathName, outType)
# }}}
# {{{ exportBitmapToImgur(self, apiKey, canvasBitmap, imgName, imgTitle, imgType): XXX
def exportBitmapToImgur(self, apiKey, canvasBitmap, imgName, imgTitle, imgType):
tmpPathName = tempfile.mkstemp()
os.close(tmpPathName[0])
canvasBitmap.ConvertToImage().SaveFile(tmpPathName[1], imgType)
imgurResult = self._exportFileToImgur(apiKey, imgName, imgTitle, tmpPathName[1])
os.remove(tmpPathName[1])
return imgurResult
# }}}
# {{{ exportPastebin(self, apiDevKey, canvasMap, canvasSize, pasteName="", pastePrivate=0): XXX
def exportPastebin(self, apiDevKey, canvasMap, canvasSize, pasteName="", pastePrivate=0):
if haveUrllib:
outFile = io.StringIO()
self.exportTextFile(canvasMap, canvasSize, outFile)
requestData = { \
"api_dev_key": apiDevKey, \
"api_option": "paste", \
"api_paste_code": outFile.getvalue().encode(), \
"api_paste_name": pasteName, \
"api_paste_private": pastePrivate}
responseHttp = requests.post("https://pastebin.com/api/api_post.php", \
data=requestData)
if responseHttp.status_code == 200:
if responseHttp.text.startswith("http"):
return (True, responseHttp.text)
else:
return (False, responseHttp.text)
else:
return (False, str(responseHttp.status_code))
else:
return (False, "missing requests and/or urllib3 module(s)")
# }}}
# {{{ exportPngFile(self, canvasMap, outPathName): XXX
def exportPngFile(self, canvasMap, outPathName):
if haveMiRCARTToPngFile:
MiRCARTToPngFile(canvasMap).export(outPathName)
return True
else:
return False
# }}}
# {{{ exportTextFile(self, canvasMap, canvasSize, outFile): XXX
def exportTextFile(self, canvasMap, canvasSize, outFile):
for canvasRow in range(canvasSize[1]):
canvasLastColours = []
for canvasCol in range(canvasSize[0]):
canvasColColours = canvasMap[canvasRow][canvasCol][0]
canvasColText = canvasMap[canvasRow][canvasCol][2]
if canvasColColours != canvasLastColours:
canvasLastColours = canvasColColours
outFile.write("\x03" + \
str(canvasColColours[0]) + \
"," + str(canvasColColours[1]))
outFile.write(canvasColText)
outFile.write("\n")
# }}}
#
# __init__(self, parentCanvas): initialisation method
def __init__(self, parentCanvas):
self.parentCanvas = parentCanvas
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,335 @@
#!/usr/bin/env python3
#
# MiRCARTCanvasInterface.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
from MiRCARTToolCircle import MiRCARTToolCircle
from MiRCARTToolFill import MiRCARTToolFill
from MiRCARTToolLine import MiRCARTToolLine
from MiRCARTToolSelectClone import MiRCARTToolSelectClone
from MiRCARTToolSelectMove import MiRCARTToolSelectMove
from MiRCARTToolRect import MiRCARTToolRect
from MiRCARTToolText import MiRCARTToolText
import os, wx
class MiRCARTCanvasInterface():
"""XXX"""
imgurApiKey = None
parentCanvas = parentFrame = canvasPathName = canvasTool = None
# {{{ _dialogSaveChanges(self)
def _dialogSaveChanges(self):
with wx.MessageDialog(self.parentCanvas, \
"Do you want to save changes to {}?".format( \
self.canvasPathName), "MiRCART", \
wx.CANCEL|wx.CANCEL_DEFAULT|wx.ICON_QUESTION|wx.YES_NO) as dialog:
dialogChoice = dialog.ShowModal()
return dialogChoice
# }}}
# {{{ canvasBrushSolid(self, event): XXX
def canvasBrushSolid(self, event):
pass
# }}}
# {{{ canvasColour(self, event, numColour): XXX
def canvasColour(self, event, numColour):
if event.GetEventType() == wx.wxEVT_TOOL:
self.parentCanvas.brushColours[0] = numColour
elif event.GetEventType() == wx.wxEVT_TOOL_RCLICKED:
self.parentCanvas.brushColours[1] = numColour
self.parentFrame.onCanvasUpdate(colours=self.parentCanvas.brushColours)
# }}}
# {{{ canvasCopy(self, event): XXX
def canvasCopy(self, event):
pass
# }}}
# {{{ canvasCut(self, event): XXX
def canvasCut(self, event):
pass
# }}}
# {{{ canvasDecrBrushHeight(self, event): XXX
def canvasDecrBrushHeight(self, event):
if self.parentCanvas.brushSize[1] > 1:
self.parentCanvas.brushSize[1] -= 1
self.parentFrame.onCanvasUpdate(brushSize=self.parentCanvas.brushSize)
# }}}
# {{{ canvasDecrBrushHeightWidth(self, event): XXX
def canvasDecrBrushHeightWidth(self, event):
self.canvasDecrBrushHeight(event)
self.canvasDecrBrushWidth(event)
# }}}
# {{{ canvasDecrBrushWidth(self, event): XXX
def canvasDecrBrushWidth(self, event):
if self.parentCanvas.brushSize[0] > 1:
self.parentCanvas.brushSize[0] -= 1
self.parentFrame.onCanvasUpdate(brushSize=self.parentCanvas.brushSize)
# }}}
# {{{ canvasDecrCanvasHeight(self, event): XXX
def canvasDecrCanvasHeight(self, event):
if self.parentCanvas.canvasSize[1] > 1:
self.parentCanvas.resize([ \
self.parentCanvas.canvasSize[0], \
self.parentCanvas.canvasSize[1]-1])
# }}}
# {{{ canvasDecrCanvasHeightWidth(self, event): XXX
def canvasDecrCanvasHeightWidth(self, event):
self.canvasDecrCanvasHeight(event)
self.canvasDecrCanvasWidth(event)
# }}}
# {{{ canvasDecrCanvasWidth(self, event): XXX
def canvasDecrCanvasWidth(self, event):
if self.parentCanvas.canvasSize[0] > 1:
self.parentCanvas.resize([ \
self.parentCanvas.canvasSize[0]-1, \
self.parentCanvas.canvasSize[1]])
# }}}
# {{{ canvasDelete(self, event): XXX
def canvasDelete(self, event):
pass
# }}}
# {{{ canvasExit(self, event): XXX
def canvasExit(self, event):
if self.canvasPathName != None:
saveChanges = self._dialogSaveChanges()
if saveChanges == wx.ID_CANCEL:
return
elif saveChanges == wx.ID_NO:
pass
elif saveChanges == wx.ID_YES:
self.canvasSave(event)
self.parentFrame.Close(True)
# }}}
# {{{ canvasExportAsPng(self, event): XXX
def canvasExportAsPng(self, event):
with wx.FileDialog(self, "Save As...", os.getcwd(), "", \
"*.png", wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dialog:
if dialog.ShowModal() == wx.ID_CANCEL:
return False
else:
outPathName = dialog.GetPath()
self.parentCanvas.SetCursor(wx.Cursor(wx.CURSOR_WAIT))
self.parentCanvas.canvasExportStore.exportBitmapToPngFile( \
self.parentCanvas.canvasBackend.canvasBitmap, outPathName, \
wx.BITMAP_TYPE_PNG)
self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor))
return True
# }}}
# {{{ canvasExportImgur(self, event): XXX
def canvasExportImgur(self, event):
self.parentCanvas.SetCursor(wx.Cursor(wx.CURSOR_WAIT))
imgurResult = self.parentCanvas.canvasExportStore.exportBitmapToImgur( \
self.imgurApiKey, self.parentCanvas.canvasBackend.canvasBitmap, \
"", "", wx.BITMAP_TYPE_PNG)
self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor))
if imgurResult[0] == 200:
if not wx.TheClipboard.IsOpened():
wx.TheClipboard.Open()
wx.TheClipboard.SetData(wx.TextDataObject(imgurResult[1]))
wx.TheClipboard.Close()
wx.MessageBox("Exported to Imgur: " + imgurResult[1], \
"Export to Imgur", wx.OK|wx.ICON_INFORMATION)
else:
wx.MessageBox("Failed to export to Imgur: " + imgurResult[1], \
"Export to Imgur", wx.OK|wx.ICON_EXCLAMATION)
# }}}
# {{{ canvasExportPastebin(self, event): XXX
def canvasExportPastebin(self, event):
self.parentCanvas.SetCursor(wx.Cursor(wx.CURSOR_WAIT))
pasteStatus, pasteResult = \
self.parentCanvas.canvasExportStore.exportPastebin( \
"", \
self.parentCanvas.canvasMap, \
self.parentCanvas.canvasSize)
self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor))
if pasteStatus:
if not wx.TheClipboard.IsOpened():
wx.TheClipboard.Open()
wx.TheClipboard.SetData(wx.TextDataObject(pasteResult))
wx.TheClipboard.Close()
wx.MessageBox("Exported to Pastebin: " + pasteResult, \
"Export to Pastebin", wx.OK|wx.ICON_INFORMATION)
else:
wx.MessageBox("Failed to export to Pastebin: " + pasteResult, \
"Export to Pastebin", wx.OK|wx.ICON_EXCLAMATION)
# }}}
# {{{ canvasIncrBrushHeight(self, event): XXX
def canvasIncrBrushHeight(self, event):
self.parentCanvas.brushSize[1] += 1
self.parentFrame.onCanvasUpdate(brushSize=self.parentCanvas.brushSize)
# }}}
# {{{ canvasIncrBrushHeightWidth(self, event): XXX
def canvasIncrBrushHeightWidth(self, event):
self.canvasIncrBrushHeight(event)
self.canvasIncrBrushWidth(event)
# }}}
# {{{ canvasIncrBrushWidth(self, event): XXX
def canvasIncrBrushWidth(self, event):
self.parentCanvas.brushSize[0] += 1
self.parentFrame.onCanvasUpdate(brushSize=self.parentCanvas.brushSize)
# }}}
# {{{ canvasIncrCanvasHeight(self, event): XXX
def canvasIncrCanvasHeight(self, event):
self.parentCanvas.resize([ \
self.parentCanvas.canvasSize[0], \
self.parentCanvas.canvasSize[1]+1])
# }}}
# {{{ canvasIncrCanvasHeightWidth(self, event): XXX
def canvasIncrCanvasHeightWidth(self, event):
self.canvasIncrCanvasHeight(event)
self.canvasIncrCanvasWidth(event)
# }}}
# {{{ canvasIncrCanvasWidth(self, event): XXX
def canvasIncrCanvasWidth(self, event):
self.parentCanvas.resize([ \
self.parentCanvas.canvasSize[0]+1, \
self.parentCanvas.canvasSize[1]])
# }}}
# {{{ canvasNew(self, event, newCanvasSize=None): XXX
def canvasNew(self, event, newCanvasSize=None):
if self.canvasPathName != None:
saveChanges = self._dialogSaveChanges()
if saveChanges == wx.ID_CANCEL:
return
elif saveChanges == wx.ID_NO:
pass
elif saveChanges == wx.ID_YES:
self.canvasSave(event)
self.parentCanvas.SetCursor(wx.Cursor(wx.CURSOR_WAIT))
if newCanvasSize == None:
newCanvasSize = list(self.parentCanvas.defaultCanvasSize)
self.parentCanvas.canvasImportStore.importNew(newCanvasSize)
self.canvasPathName = None
self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor))
self.parentFrame.onCanvasUpdate(pathName="", undoLevel=-1)
# }}}
# {{{ canvasOpen(self, event): XXX
def canvasOpen(self, event):
if self.canvasPathName != None:
saveChanges = self._dialogSaveChanges()
if saveChanges == wx.ID_CANCEL:
return
elif saveChanges == wx.ID_NO:
pass
elif saveChanges == wx.ID_YES:
self.canvasSave(event)
with wx.FileDialog(self.parentCanvas, "Open", os.getcwd(), "", \
"*.txt", wx.FD_OPEN) as dialog:
if dialog.ShowModal() == wx.ID_CANCEL:
return False
else:
self.canvasPathName = dialog.GetPath()
self.parentCanvas.SetCursor(wx.Cursor(wx.CURSOR_WAIT))
self.parentCanvas.canvasImportStore.importTextFile(self.canvasPathName)
self.parentCanvas.canvasImportStore.importIntoPanel()
self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor))
self.parentFrame.onCanvasUpdate( \
pathName=self.canvasPathName, undoLevel=-1)
return True
# }}}
# {{{ canvasPaste(self, event): XXX
def canvasPaste(self, event):
pass
# }}}
# {{{ canvasRedo(self, event): XXX
def canvasRedo(self, event):
self.parentCanvas._dispatchDeltaPatches( \
self.parentCanvas.canvasJournal.popRedo())
# }}}
# {{{ canvasSave(self, event): XXX
def canvasSave(self, event):
if self.canvasPathName == None:
if self.canvasSaveAs(event) == False:
return
try:
with open(self.canvasPathName, "w") as outFile:
self.parentCanvas.SetCursor(wx.Cursor(wx.CURSOR_WAIT))
self.parentCanvas.canvasExportStore.exportTextFile( \
self.parentCanvas.canvasMap, \
self.parentCanvas.canvasSize, outFile)
self.parentCanvas.SetCursor(wx.Cursor(wx.NullCursor))
return True
except IOError as error:
return False
# }}}
# {{{ canvasSaveAs(self, event): XXX
def canvasSaveAs(self, event):
with wx.FileDialog(self.parentCanvas, "Save As", os.getcwd(), "", \
"*.txt", wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dialog:
if dialog.ShowModal() == wx.ID_CANCEL:
return False
else:
self.canvasPathName = dialog.GetPath()
return self.canvasSave(event)
# }}}
# {{{ canvasToolCircle(self, event): XXX
def canvasToolCircle(self, event):
self.canvasTool = MiRCARTToolCircle(self.parentCanvas)
self.parentFrame.menuItemsById[self.parentFrame.CID_CIRCLE[0]].Check(True)
toolBar = self.parentFrame.toolBarItemsById[self.parentFrame.CID_CIRCLE[0]].GetToolBar()
toolBar.ToggleTool(self.parentFrame.CID_CIRCLE[0], True)
self.parentFrame.onCanvasUpdate(toolName=self.canvasTool.name)
# }}}
# {{{ canvasToolFill(self, event): XXX
def canvasToolFill(self, event):
self.canvasTool = MiRCARTToolFill(self.parentCanvas)
self.parentFrame.menuItemsById[self.parentFrame.CID_FILL[0]].Check(True)
toolBar = self.parentFrame.toolBarItemsById[self.parentFrame.CID_FILL[0]].GetToolBar()
toolBar.ToggleTool(self.parentFrame.CID_FILL[0], True)
self.parentFrame.onCanvasUpdate(toolName=self.canvasTool.name)
# }}}
# {{{ canvasToolLine(self, event): XXX
def canvasToolLine(self, event):
self.canvasTool = MiRCARTToolLine(self.parentCanvas)
self.parentFrame.menuItemsById[self.parentFrame.CID_LINE[0]].Check(True)
toolBar = self.parentFrame.toolBarItemsById[self.parentFrame.CID_LINE[0]].GetToolBar()
toolBar.ToggleTool(self.parentFrame.CID_LINE[0], True)
self.parentFrame.onCanvasUpdate(toolName=self.canvasTool.name)
# }}}
# {{{ canvasToolSelectClone(self, event): XXX
def canvasToolSelectClone(self, event):
self.canvasTool = MiRCARTToolSelectClone(self.parentCanvas)
self.parentFrame.menuItemsById[self.parentFrame.CID_CLONE_SELECT[0]].Check(True)
toolBar = self.parentFrame.toolBarItemsById[self.parentFrame.CID_CLONE_SELECT[0]].GetToolBar()
toolBar.ToggleTool(self.parentFrame.CID_CLONE_SELECT[0], True)
self.parentFrame.onCanvasUpdate(toolName=self.canvasTool.name)
# }}}
# {{{ canvasToolSelectMove(self, event): XXX
def canvasToolSelectMove(self, event):
self.canvasTool = MiRCARTToolSelectMove(self.parentCanvas)
self.parentFrame.menuItemsById[self.parentFrame.CID_MOVE_SELECT[0]].Check(True)
toolBar = self.parentFrame.toolBarItemsById[self.parentFrame.CID_MOVE_SELECT[0]].GetToolBar()
toolBar.ToggleTool(self.parentFrame.CID_MOVE_SELECT[0], True)
self.parentFrame.onCanvasUpdate(toolName=self.canvasTool.name)
# }}}
# {{{ canvasToolRect(self, event): XXX
def canvasToolRect(self, event):
self.canvasTool = MiRCARTToolRect(self.parentCanvas)
self.parentFrame.menuItemsById[self.parentFrame.CID_RECT[0]].Check(True)
toolBar = self.parentFrame.toolBarItemsById[self.parentFrame.CID_RECT[0]].GetToolBar()
toolBar.ToggleTool(self.parentFrame.CID_RECT[0], True)
self.parentFrame.onCanvasUpdate(toolName=self.canvasTool.name)
# }}}
# {{{ canvasToolText(self, event): XXX
def canvasToolText(self, event):
self.canvasTool = MiRCARTToolText(self.parentCanvas)
self.parentFrame.menuItemsById[self.parentFrame.CID_TEXT[0]].Check(True)
toolBar = self.parentFrame.toolBarItemsById[self.parentFrame.CID_TEXT[0]].GetToolBar()
toolBar.ToggleTool(self.parentFrame.CID_TEXT[0], True)
self.parentFrame.onCanvasUpdate(toolName=self.canvasTool.name)
# }}}
# {{{ canvasUndo(self, event): XXX
def canvasUndo(self, event):
self.parentCanvas._dispatchDeltaPatches( \
self.parentCanvas.canvasJournal.popUndo())
# }}}
#
# __init__(self, parentCanvas, parentFrame):
def __init__(self, parentCanvas, parentFrame):
self.parentCanvas = parentCanvas; self.parentFrame = parentFrame;
self.canvasPathName = None
self.canvasToolRect(None)
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,79 @@
#!/usr/bin/env python3
#
# MiRCARTCanvasJournal.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
class MiRCARTCanvasJournal():
"""XXX"""
patchesCursor = patchesUndo = patchesUndoLevel = None
# {{{ popCursor(self): XXX
def popCursor(self):
if len(self.patchesCursor):
patchesCursor = self.patchesCursor
self.patchesCursor = []
return patchesCursor
else:
return []
# }}}
# {{{ popRedo(self): XXX
def popRedo(self):
if self.patchesUndoLevel > 0:
self.patchesUndoLevel -= 1
patches = self.patchesUndo[self.patchesUndoLevel]
return patches[1]
else:
return []
# }}}
# {{{ popUndo(self): XXX
def popUndo(self):
if self.patchesUndo[self.patchesUndoLevel] != None:
patches = self.patchesUndo[self.patchesUndoLevel]
self.patchesUndoLevel += 1
return patches[0]
else:
return []
# }}}
# {{{ pushCursor(self, patches): XXX
def pushCursor(self, patches):
self.patchesCursor.append(patches)
# }}}
# {{{ pushDeltas(self, undoPatches, redoPatches): XXX
def pushDeltas(self, undoPatches, redoPatches):
if self.patchesUndoLevel > 0:
del self.patchesUndo[0:self.patchesUndoLevel]
self.patchesUndoLevel = 0
deltaItem = [undoPatches, redoPatches]
self.patchesUndo.insert(0, deltaItem)
return deltaItem
# }}}
# {{{ resetCursor(self): XXX
def resetCursor(self):
if self.patchesCursor != None:
self.patchesCursor.clear()
self.patchesCursor = []
# }}}
# {{{ resetUndo(self): XXX
def resetUndo(self):
if self.patchesUndo != None:
self.patchesUndo.clear()
self.patchesUndo = [None]; self.patchesUndoLevel = 0;
# }}}
# {{{ updateCurrentDeltas(self, undoPatches, redoPatches): XXX
def updateCurrentDeltas(self, undoPatches, redoPatches):
self.patchesUndo[0][0].append(undoPatches)
self.patchesUndo[0][1].append(redoPatches)
# }}}
# {{{ __del__(self): destructor method
def __del__(self):
self.resetCursor(); self.resetUndo();
# }}}
#
# __init__(self): initialisation method
def __init__(self):
self.resetCursor(); self.resetUndo();
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,29 @@
#!/usr/bin/env python3
#
# MiRCARTColours.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
#
# MiRCARTColours: mIRC colour number to RGBA map given none of ^[BFV_] (bold, italic, reverse, underline],
#
MiRCARTColours = [
[255, 255, 255, 255, "White"],
[0, 0, 0, 255, "Black"],
[0, 0, 187, 255, "Blue"],
[0, 187, 0, 255, "Green"],
[255, 85, 85, 255, "Light Red"],
[187, 0, 0, 255, "Red"],
[187, 0, 187, 255, "Purple"],
[187, 187, 0, 255, "Yellow"],
[255, 255, 85, 255, "Light Yellow"],
[85, 255, 85, 255, "Light Green"],
[0, 187, 187, 255, "Cyan"],
[85, 255, 255, 255, "Light Cyan"],
[85, 85, 255, 255, "Light Blue"],
[255, 85, 255, 255, "Pink"],
[85, 85, 85, 255, "Grey"],
[187, 187, 187, 255, "Light Grey"],
]
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

234
libgui/MiRCARTFrame.py Normal file
View File

@ -0,0 +1,234 @@
#!/usr/bin/env python3
#
# MiRCARTFrame.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
from MiRCARTCanvas import MiRCARTCanvas, haveUrllib
from MiRCARTCanvasInterface import MiRCARTCanvasInterface
from MiRCARTColours import MiRCARTColours
from MiRCARTGeneralFrame import MiRCARTGeneralFrame, \
TID_ACCELS, TID_COMMAND, TID_LIST, TID_MENU, TID_NOTHING, TID_SELECT, TID_TOOLBAR, \
NID_MENU_SEP, NID_TOOLBAR_HSEP, NID_TOOLBAR_VSEP
import os, wx
class MiRCARTFrame(MiRCARTGeneralFrame):
"""XXX"""
panelCanvas = None; lastPanelState = {};
# {{{ Commands
# Id Type Id Labels Icon bitmap Accelerator [Initial state]
CID_NEW = [0x100, TID_COMMAND, "New", "&New", ["", wx.ART_NEW], [wx.ACCEL_CTRL, ord("N")], None, MiRCARTCanvasInterface.canvasNew]
CID_OPEN = [0x101, TID_COMMAND, "Open", "&Open", ["", wx.ART_FILE_OPEN], [wx.ACCEL_CTRL, ord("O")], None, MiRCARTCanvasInterface.canvasOpen]
CID_SAVE = [0x102, TID_COMMAND, "Save", "&Save", ["", wx.ART_FILE_SAVE], [wx.ACCEL_CTRL, ord("S")], None, MiRCARTCanvasInterface.canvasSave]
CID_SAVEAS = [0x103, TID_COMMAND, "Save As...", "Save &As...", ["", wx.ART_FILE_SAVE_AS], None, None, MiRCARTCanvasInterface.canvasSaveAs]
CID_EXPORT_AS_PNG = [0x104, TID_COMMAND, "Export as PNG...", \
"Export as PN&G...", None, None, None, MiRCARTCanvasInterface.canvasExportAsPng]
CID_EXPORT_IMGUR = [0x105, TID_COMMAND, "Export to Imgur...", \
"Export to I&mgur...", None, None, haveUrllib, MiRCARTCanvasInterface.canvasExportImgur]
CID_EXPORT_PASTEBIN = [0x106, TID_COMMAND, "Export to Pastebin...", \
"Export to Pasteb&in...", None, None, haveUrllib, MiRCARTCanvasInterface.canvasExportPastebin]
CID_EXIT = [0x107, TID_COMMAND, "Exit", "E&xit", None, [wx.ACCEL_CTRL, ord("X")], None, MiRCARTCanvasInterface.canvasExit]
CID_UNDO = [0x108, TID_COMMAND, "Undo", "&Undo", ["", wx.ART_UNDO], [wx.ACCEL_CTRL, ord("Z")], False, MiRCARTCanvasInterface.canvasUndo]
CID_REDO = [0x109, TID_COMMAND, "Redo", "&Redo", ["", wx.ART_REDO], [wx.ACCEL_CTRL, ord("Y")], False, MiRCARTCanvasInterface.canvasRedo]
CID_CUT = [0x10a, TID_COMMAND, "Cut", "Cu&t", ["", wx.ART_CUT], None, False, MiRCARTCanvasInterface.canvasCut]
CID_COPY = [0x10b, TID_COMMAND, "Copy", "&Copy", ["", wx.ART_COPY], None, False, MiRCARTCanvasInterface.canvasCopy]
CID_PASTE = [0x10c, TID_COMMAND, "Paste", "&Paste", ["", wx.ART_PASTE], None, False, MiRCARTCanvasInterface.canvasPaste]
CID_DELETE = [0x10d, TID_COMMAND, "Delete", "De&lete", ["", wx.ART_DELETE], None, False, MiRCARTCanvasInterface.canvasDelete]
CID_INCRW_CANVAS = [0x10e, TID_COMMAND, "Increase canvas width", \
"Increase canvas width", ["toolIncrCanvasW.png"], None, None, MiRCARTCanvasInterface.canvasIncrCanvasWidth]
CID_DECRW_CANVAS = [0x10f, TID_COMMAND, "Decrease canvas width", \
"Decrease canvas width", ["toolDecrCanvasW.png"], None, None, MiRCARTCanvasInterface.canvasDecrCanvasWidth]
CID_INCRH_CANVAS = [0x110, TID_COMMAND, "Increase canvas height", \
"Increase canvas height", ["toolIncrCanvasH.png"], None, None, MiRCARTCanvasInterface.canvasIncrCanvasHeight]
CID_DECRH_CANVAS = [0x111, TID_COMMAND, "Decrease canvas height", \
"Decrease canvas height", ["toolDecrCanvasH.png"], None, None, MiRCARTCanvasInterface.canvasDecrCanvasHeight]
CID_INCRHW_CANVAS = [0x112, TID_COMMAND, "Increase canvas size", \
"Increase canvas size", ["toolIncrCanvasHW.png"], None, None, MiRCARTCanvasInterface.canvasIncrCanvasHeightWidth]
CID_DECRHW_CANVAS = [0x113, TID_COMMAND, "Decrease canvas size", \
"Decrease canvas size", ["toolDecrCanvasHW.png"], None, None, MiRCARTCanvasInterface.canvasDecrCanvasHeightWidth]
CID_INCRW_BRUSH = [0x114, TID_COMMAND, "Increase brush width", \
"Increase brush width", ["toolIncrBrushW.png"], None, None, MiRCARTCanvasInterface.canvasIncrBrushWidth]
CID_DECRW_BRUSH = [0x115, TID_COMMAND, "Decrease brush width", \
"Decrease brush width", ["toolDecrBrushW.png"], None, None, MiRCARTCanvasInterface.canvasDecrBrushWidth]
CID_INCRH_BRUSH = [0x116, TID_COMMAND, "Increase brush height", \
"Increase brush height", ["toolIncrBrushH.png"], None, None, MiRCARTCanvasInterface.canvasIncrBrushHeight]
CID_DECRH_BRUSH = [0x117, TID_COMMAND, "Decrease brush height", \
"Decrease brush height", ["toolDecrBrushH.png"], None, None, MiRCARTCanvasInterface.canvasDecrBrushHeight]
CID_INCRHW_BRUSH = [0x118, TID_COMMAND, "Increase brush size", \
"Increase brush size", ["toolIncrBrushHW.png"], None, None, MiRCARTCanvasInterface.canvasIncrBrushHeightWidth]
CID_DECRHW_BRUSH = [0x119, TID_COMMAND, "Decrease brush size", \
"Decrease brush size", ["toolDecrBrushHW.png"], None, None, MiRCARTCanvasInterface.canvasDecrBrushHeightWidth]
CID_SOLID_BRUSH = [0x11a, TID_SELECT, "Solid brush", "Solid brush", None, None, True, MiRCARTCanvasInterface.canvasBrushSolid]
CID_RECT = [0x150, TID_SELECT, "Rectangle", "&Rectangle", ["toolRect.png"], [wx.ACCEL_CTRL, ord("R")], True, MiRCARTCanvasInterface.canvasToolRect]
CID_CIRCLE = [0x151, TID_SELECT, "Circle", "&Circle", ["toolCircle.png"], [wx.ACCEL_CTRL, ord("C")], False, MiRCARTCanvasInterface.canvasToolCircle]
CID_FILL = [0x152, TID_SELECT, "Fill", "&Fill", ["toolFill.png"], [wx.ACCEL_CTRL, ord("F")], False, MiRCARTCanvasInterface.canvasToolFill]
CID_LINE = [0x153, TID_SELECT, "Line", "&Line", ["toolLine.png"], [wx.ACCEL_CTRL, ord("L")], False, MiRCARTCanvasInterface.canvasToolLine]
CID_TEXT = [0x154, TID_SELECT, "Text", "&Text", ["toolText.png"], [wx.ACCEL_CTRL, ord("T")], False, MiRCARTCanvasInterface.canvasToolText]
CID_CLONE_SELECT = [0x155, TID_SELECT, "Clone", "Cl&one", ["toolClone.png"], [wx.ACCEL_CTRL, ord("E")], False, MiRCARTCanvasInterface.canvasToolSelectClone]
CID_MOVE_SELECT = [0x156, TID_SELECT, "Move", "&Move", ["toolMove.png"], [wx.ACCEL_CTRL, ord("M")], False, MiRCARTCanvasInterface.canvasToolSelectMove]
CID_COLOUR00 = [0x1a0, TID_SELECT, "Colour #00", "Colour #00", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR01 = [0x1a1, TID_SELECT, "Colour #01", "Colour #01", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR02 = [0x1a2, TID_SELECT, "Colour #02", "Colour #02", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR03 = [0x1a3, TID_SELECT, "Colour #03", "Colour #03", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR04 = [0x1a4, TID_SELECT, "Colour #04", "Colour #04", None, None, True, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR05 = [0x1a5, TID_SELECT, "Colour #05", "Colour #05", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR06 = [0x1a6, TID_SELECT, "Colour #06", "Colour #06", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR07 = [0x1a7, TID_SELECT, "Colour #07", "Colour #07", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR08 = [0x1a8, TID_SELECT, "Colour #08", "Colour #08", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR09 = [0x1a9, TID_SELECT, "Colour #09", "Colour #09", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR10 = [0x1aa, TID_SELECT, "Colour #10", "Colour #10", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR11 = [0x1ab, TID_SELECT, "Colour #11", "Colour #11", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR12 = [0x1ac, TID_SELECT, "Colour #12", "Colour #12", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR13 = [0x1ad, TID_SELECT, "Colour #13", "Colour #13", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR14 = [0x1ae, TID_SELECT, "Colour #14", "Colour #14", None, None, False, MiRCARTCanvasInterface.canvasColour]
CID_COLOUR15 = [0x1af, TID_SELECT, "Colour #15", "Colour #15", None, None, False, MiRCARTCanvasInterface.canvasColour]
# }}}
# {{{ Menus
MID_FILE = (0x300, TID_MENU, "File", "&File", ( \
CID_NEW, CID_OPEN, CID_SAVE, CID_SAVEAS, NID_MENU_SEP, \
CID_EXPORT_AS_PNG, CID_EXPORT_IMGUR, CID_EXPORT_PASTEBIN, NID_MENU_SEP, \
CID_EXIT))
MID_EDIT = (0x301, TID_MENU, "Edit", "&Edit", ( \
CID_UNDO, CID_REDO, NID_MENU_SEP, \
CID_CUT, CID_COPY, CID_PASTE, CID_DELETE, NID_MENU_SEP, \
CID_INCRW_CANVAS, CID_DECRW_CANVAS, CID_INCRH_CANVAS, CID_DECRH_CANVAS, NID_MENU_SEP, \
CID_INCRHW_CANVAS, CID_DECRHW_CANVAS, NID_MENU_SEP, \
CID_INCRW_BRUSH, CID_DECRW_BRUSH, CID_INCRH_BRUSH, CID_DECRH_BRUSH, NID_MENU_SEP, \
CID_INCRHW_BRUSH, CID_DECRHW_BRUSH, NID_MENU_SEP, \
CID_SOLID_BRUSH))
MID_TOOLS = (0x302, TID_MENU, "Tools", "&Tools", ( \
CID_RECT, CID_CIRCLE, CID_FILL, CID_LINE, CID_TEXT, CID_CLONE_SELECT, CID_MOVE_SELECT))
# }}}
# {{{ Toolbars
BID_TOOLBAR = (0x400, TID_TOOLBAR, ( \
CID_NEW, CID_OPEN, CID_SAVE, CID_SAVEAS, NID_TOOLBAR_HSEP, \
CID_UNDO, CID_REDO, NID_TOOLBAR_HSEP, \
CID_CUT, CID_COPY, CID_PASTE, CID_DELETE, NID_TOOLBAR_HSEP, \
CID_INCRW_CANVAS, CID_DECRW_CANVAS, CID_INCRH_CANVAS, CID_DECRH_CANVAS, NID_TOOLBAR_HSEP, \
CID_INCRHW_CANVAS, CID_DECRHW_CANVAS, NID_TOOLBAR_HSEP, \
CID_RECT, CID_CIRCLE, CID_FILL, CID_LINE, CID_TEXT, CID_CLONE_SELECT, CID_MOVE_SELECT, \
NID_TOOLBAR_VSEP, \
CID_COLOUR00, CID_COLOUR01, CID_COLOUR02, CID_COLOUR03, CID_COLOUR04, \
CID_COLOUR05, CID_COLOUR06, CID_COLOUR07, CID_COLOUR08, CID_COLOUR09, \
CID_COLOUR10, CID_COLOUR11, CID_COLOUR12, CID_COLOUR13, CID_COLOUR14, \
CID_COLOUR15, NID_TOOLBAR_HSEP, \
CID_INCRW_BRUSH, CID_DECRW_BRUSH, CID_INCRH_BRUSH, CID_DECRH_BRUSH, NID_TOOLBAR_HSEP, \
CID_INCRHW_BRUSH, CID_DECRHW_BRUSH))
# }}}
# {{{ Accelerators (hotkeys)
AID_EDIT = (0x500, TID_ACCELS, ( \
CID_NEW, CID_OPEN, CID_SAVE, CID_EXIT, CID_UNDO, CID_REDO, \
CID_RECT, CID_CIRCLE, CID_FILL, CID_LINE, CID_TEXT, CID_CLONE_SELECT, CID_MOVE_SELECT))
# }}}
# {{{ Lists
LID_ACCELS = (0x600, TID_LIST, (AID_EDIT))
LID_MENUS = (0x601, TID_LIST, (MID_FILE, MID_EDIT, MID_TOOLS))
LID_TOOLBARS = (0x602, TID_LIST, (BID_TOOLBAR))
# }}}
# {{{ _initPaletteToolBitmaps(self): XXX
def _initPaletteToolBitmaps(self):
paletteDescr = ( \
self.CID_COLOUR00, self.CID_COLOUR01, self.CID_COLOUR02, self.CID_COLOUR03, self.CID_COLOUR04, \
self.CID_COLOUR05, self.CID_COLOUR06, self.CID_COLOUR07, self.CID_COLOUR08, self.CID_COLOUR09, \
self.CID_COLOUR10, self.CID_COLOUR11, self.CID_COLOUR12, self.CID_COLOUR13, self.CID_COLOUR14, \
self.CID_COLOUR15)
for numColour in range(len(paletteDescr)):
toolBitmapColour = MiRCARTColours[numColour][0:4]
toolBitmap = wx.Bitmap((16,16))
toolBitmapDc = wx.MemoryDC(); toolBitmapDc.SelectObject(toolBitmap);
toolBitmapBrush = wx.Brush( \
wx.Colour(toolBitmapColour), wx.BRUSHSTYLE_SOLID)
toolBitmapDc.SetBrush(toolBitmapBrush)
toolBitmapDc.SetBackground(toolBitmapBrush)
toolBitmapDc.SetPen(wx.Pen(wx.Colour(toolBitmapColour), 1))
toolBitmapDc.DrawRectangle(0, 0, 16, 16)
paletteDescr[numColour][4] = ["", None, toolBitmap]
# }}}
# {{{ onInput(self, event): XXX
def onInput(self, event):
eventId = event.GetId()
if eventId >= self.CID_COLOUR00[0] \
and eventId <= self.CID_COLOUR15[0]:
numColour = eventId - self.CID_COLOUR00[0]
self.itemsById[eventId][7](self.panelCanvas.canvasInterface, event, numColour)
else:
self.itemsById[eventId][7](self.panelCanvas.canvasInterface, event)
# }}}
# {{{ onCanvasUpdate(self, newBrushSize=None, newCellPos=None, newColours=None, newPathName=None, newSize=None, newToolName=None, newUndoLevel=None): XXX
def onCanvasUpdate(self, **kwargs):
self.lastPanelState.update(kwargs)
textItems = []
if "cellPos" in self.lastPanelState:
textItems.append("X: {:03d} Y: {:03d}".format( \
*self.lastPanelState["cellPos"]))
if "size" in self.lastPanelState:
textItems.append("W: {:03d} H: {:03d}".format( \
*self.lastPanelState["size"]))
if "brushSize" in self.lastPanelState:
textItems.append("Brush: {:02d}x{:02d}".format( \
*self.lastPanelState["brushSize"]))
if "colours" in self.lastPanelState:
textItems.append("FG: {:02d}, BG: {:02d}".format( \
*self.lastPanelState["colours"]))
textItems.append("{} on {}".format( \
MiRCARTColours[self.lastPanelState["colours"][0]][4], \
MiRCARTColours[self.lastPanelState["colours"][1]][4]))
if "pathName" in self.lastPanelState:
if self.lastPanelState["pathName"] != "":
basePathName = os.path.basename(self.lastPanelState["pathName"])
textItems.append("Current file: {}".format(basePathName))
self.SetTitle("{} - MiRCART".format(basePathName))
else:
self.SetTitle("MiRCART")
if "toolName" in self.lastPanelState:
textItems.append("Current tool: {}".format( \
self.lastPanelState["toolName"]))
self.statusBar.SetStatusText(" | ".join(textItems))
if "undoLevel" in self.lastPanelState:
if self.lastPanelState["undoLevel"] >= 0:
self.menuItemsById[self.CID_UNDO[0]].Enable(True)
toolBar = self.toolBarItemsById[self.CID_UNDO[0]].GetToolBar()
toolBar.EnableTool(self.CID_UNDO[0], True)
else:
self.menuItemsById[self.CID_UNDO[0]].Enable(False)
toolBar = self.toolBarItemsById[self.CID_UNDO[0]].GetToolBar()
toolBar.EnableTool(self.CID_UNDO[0], False)
if self.lastPanelState["undoLevel"] > 0:
self.menuItemsById[self.CID_REDO[0]].Enable(True)
toolBar = self.toolBarItemsById[self.CID_REDO[0]].GetToolBar()
toolBar.EnableTool(self.CID_REDO[0], True)
else:
self.menuItemsById[self.CID_REDO[0]].Enable(False)
toolBar = self.toolBarItemsById[self.CID_REDO[0]].GetToolBar()
toolBar.EnableTool(self.CID_REDO[0], False)
# }}}
# {{{ __del__(self): destructor method
def __del__(self):
if self.panelCanvas != None:
del self.panelCanvas; self.panelCanvas = None;
# }}}
#
# __init__(self, parent, appSize=(840, 630), defaultCanvasPos=(0, 75), defaultCanvasSize=(100, 30), defaultCellSize=(7, 14)): initialisation method
def __init__(self, parent, appSize=(840, 630), defaultCanvasPos=(0, 75), defaultCanvasSize=(100, 30), defaultCellSize=(7, 14)):
self._initPaletteToolBitmaps()
self.panelSkin = super().__init__(parent, wx.ID_ANY, "MiRCART", size=appSize)
self.panelCanvas = MiRCARTCanvas(self.panelSkin, parentFrame=self, \
defaultCanvasPos=defaultCanvasPos, \
defaultCanvasSize=defaultCanvasSize, \
defaultCellSize=defaultCellSize)
self.panelCanvas.canvasInterface.canvasNew(None)
self.sizerSkin.AddSpacer(5)
self.sizerSkin.Add(self.panelCanvas, 0, wx.ALL|wx.EXPAND, 14)
self.panelSkin.SetSizer(self.sizerSkin)
self.panelSkin.SetAutoLayout(1)
self.sizerSkin.Fit(self.panelSkin)
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,169 @@
#!/usr/bin/env python3
#
# MiRCARTGeneralFrame.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
import os, sys, wx
#
# Types
TID_ACCELS = (0x001)
TID_COMMAND = (0x002)
TID_LIST = (0x003)
TID_MENU = (0x004)
TID_NOTHING = (0x005)
TID_SELECT = (0x006)
TID_TOOLBAR = (0x007)
#
# Non-items
NID_MENU_SEP = (0x200, TID_NOTHING)
NID_TOOLBAR_HSEP = (0x201, TID_NOTHING)
NID_TOOLBAR_VSEP = (0x202, TID_NOTHING)
class MiRCARTGeneralFrame(wx.Frame):
"""XXX"""
accelItemsById = itemsById = menuItemsById = toolBarItemsById = None
statusBar = toolBars = None
panelSkin = sizerSkin = None
# {{{ _initAccelTable(self, accelsDescr): XXX
def _initAccelTable(self, accelsDescr):
accelTableEntries = [wx.AcceleratorEntry() for n in range(len(accelsDescr[2]))]
self.accelItemsById = {}
for numAccel in range(len(accelsDescr[2])):
accelDescr = accelsDescr[2][numAccel]
if accelDescr[5] != None:
self.itemsById[accelDescr[0]] = accelDescr
accelTableEntries[numAccel].Set(*accelDescr[5], accelDescr[0])
self.accelItemsById[accelDescr[0]] = accelTableEntries[numAccel]
self.Bind(wx.EVT_MENU, self.onInput, id=accelDescr[0])
return accelTableEntries
# }}}
# {{{ _initMenus(self, menusDescr): XXX
def _initMenus(self, menusDescr):
self.menuItemsById = {}; menuBar = wx.MenuBar();
for menuDescr in menusDescr:
menuWindow = wx.Menu()
for menuItem in menuDescr[4]:
if menuItem == NID_MENU_SEP:
menuWindow.AppendSeparator()
elif menuItem[1] == TID_SELECT:
self.itemsById[menuItem[0]] = menuItem
menuItemWindow = menuWindow.AppendRadioItem(menuItem[0], menuItem[3], menuItem[2])
if menuItem[5] != None:
menuItemWindow.SetAccel(self.accelItemsById[menuItem[0]])
self.menuItemsById[menuItem[0]] = menuItemWindow
self.Bind(wx.EVT_MENU, self.onInput, menuItemWindow)
if menuItem[6] != None:
menuItemWindow.Check(menuItem[6])
else:
self.itemsById[menuItem[0]] = menuItem
menuItemWindow = menuWindow.Append(menuItem[0], menuItem[3], menuItem[2])
if menuItem[5] != None:
menuItemWindow.SetAccel(self.accelItemsById[menuItem[0]])
self.menuItemsById[menuItem[0]] = menuItemWindow
self.Bind(wx.EVT_MENU, self.onInput, menuItemWindow)
if menuItem[6] != None:
menuItemWindow.Enable(menuItem[6])
menuBar.Append(menuWindow, menuDescr[3])
return menuBar
# }}}
# {{{ _initToolBars(self, toolBarsDescr, panelSkin): XXX
def _initToolBars(self, toolBarsDescr, panelSkin):
self.toolBarItemsById = {}
self.sizerSkin = wx.BoxSizer(wx.VERTICAL)
self.toolBars = [None]; numToolBar = 0;
for toolBarItem in toolBarsDescr[2]:
if self.toolBars[numToolBar] == None:
self.toolBars[numToolBar] = \
wx.ToolBar(panelSkin, -1, \
style=wx.HORIZONTAL|wx.TB_FLAT|wx.TB_NODIVIDER)
self.toolBars[numToolBar].SetToolBitmapSize((16,16))
if toolBarItem == NID_TOOLBAR_HSEP:
self.toolBars[numToolBar].AddSeparator()
elif toolBarItem == NID_TOOLBAR_VSEP:
numToolBar += 1; self.toolBars.append(None);
elif toolBarItem[1] == TID_SELECT:
self.itemsById[toolBarItem[0]] = toolBarItem
toolBarItemWindow = \
self.toolBars[numToolBar].AddRadioTool( \
toolBarItem[0], toolBarItem[2], toolBarItem[4][2])
self.toolBarItemsById[toolBarItem[0]] = toolBarItemWindow
if toolBarItem[6] != None:
toolBarItemWindow.Toggle(toolBarItem[6])
self.Bind(wx.EVT_TOOL, self.onInput, toolBarItemWindow)
self.Bind(wx.EVT_TOOL_RCLICKED, self.onInput, toolBarItemWindow)
else:
self.itemsById[toolBarItem[0]] = toolBarItem
toolBarItemWindow = \
self.toolBars[numToolBar].AddTool( \
toolBarItem[0], toolBarItem[2], toolBarItem[4][2])
self.toolBarItemsById[toolBarItem[0]] = toolBarItemWindow
if toolBarItem[6] != None:
toolBarItemWindow.Enable(toolBarItem[6])
self.Bind(wx.EVT_TOOL, self.onInput, toolBarItemWindow)
self.Bind(wx.EVT_TOOL_RCLICKED, self.onInput, toolBarItemWindow)
for numToolBar in range(len(self.toolBars)):
self.sizerSkin.Add( \
self.toolBars[numToolBar], 0, wx.ALL|wx.ALIGN_LEFT, 3)
self.toolBars[numToolBar].Realize()
self.toolBars[numToolBar].Fit()
# }}}
# {{{ _initToolBitmaps(self, toolBarsDescr): XXX
def _initToolBitmaps(self, toolBarsDescr):
for toolBarItem in toolBarsDescr[2]:
if toolBarItem == NID_TOOLBAR_HSEP \
or toolBarItem == NID_TOOLBAR_VSEP:
continue
elif toolBarItem[4] == None:
toolBarItem[4] = ["", None, wx.ArtProvider.GetBitmap( \
wx.ART_HELP, wx.ART_TOOLBAR, (16,16))]
elif toolBarItem[4][0] == "" \
and toolBarItem[4][1] != None:
toolBarItem[4] = ["", None, wx.ArtProvider.GetBitmap( \
toolBarItem[4][1], wx.ART_TOOLBAR, (16,16))]
elif toolBarItem[4][0] == "" \
and toolBarItem[4][1] == None:
toolBarItem[4] = ["", None, toolBarItem[4][2]]
elif toolBarItem[4][0] != "":
toolBitmapPathName = os.path.dirname(sys.argv[0])
toolBitmapPathName = os.path.join(toolBitmapPathName, \
"assets", "images", toolBarItem[4][0])
toolBitmap = wx.Bitmap((16,16))
toolBitmap.LoadFile(toolBitmapPathName, wx.BITMAP_TYPE_ANY)
toolBarItem[4] = ["", None, toolBitmap]
# }}}
# {{{ onInput(self, event): XXX
def onInput(self, event):
pass
# }}}
#
# __init__(self, *args, **kwargs): initialisation method
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs); self.itemsById = {};
panelSkin = wx.Panel(self, wx.ID_ANY)
# Initialise accelerators (hotkeys)
accelTable = wx.AcceleratorTable( \
self._initAccelTable(self.LID_ACCELS[2]))
self.SetAcceleratorTable(accelTable)
# Initialise menu bar, menus & menu items
# Initialise toolbar & toolbar items
menuBar = self._initMenus(self.LID_MENUS[2])
self.SetMenuBar(menuBar)
self._initToolBitmaps(self.LID_TOOLBARS[2])
toolBar = self._initToolBars(self.LID_TOOLBARS[2], panelSkin)
# Initialise status bar
self.statusBar = self.CreateStatusBar()
# Set focus on & show window
self.SetFocus(); self.Show(True);
return panelSkin
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

25
libtools/MiRCARTTool.py Normal file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python3
#
# MiRCARTTool.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
class MiRCARTTool():
"""XXX"""
parentCanvas = None
# {{{ onKeyboardEvent(self, event, atPoint, brushColours, brushSize, keyChar, dispatchFn, eventDc):
def onKeyboardEvent(self, event, atPoint, brushColours, brushSize, keyChar, dispatchFn, eventDc):
return True
# }}}
# {{{ onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc): XXX
def onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc):
return ()
# }}}
#
# __init__(self, parentCanvas): initialisation method
def __init__(self, parentCanvas):
self.parentCanvas = parentCanvas
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,38 @@
#!/usr/bin/env python3
#
# MiRCARTToolCircle.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
from MiRCARTTool import MiRCARTTool
class MiRCARTToolCircle(MiRCARTTool):
"""XXX"""
name = "Circle"
#
# onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc): XXX
def onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc):
brushColours = brushColours.copy()
if isLeftDown:
brushColours[1] = brushColours[0]
elif isRightDown:
brushColours[0] = brushColours[1]
else:
brushColours[1] = brushColours[0]
_brushSize = brushSize[0]*2
originPoint = (_brushSize/2, _brushSize/2)
radius = _brushSize
for brushY in range(-radius, radius + 1):
for brushX in range(-radius, radius + 1):
if ((brushX**2)+(brushY**2) < (((radius**2)+radius)*0.8)):
patch = [ \
atPoint[0] + int(originPoint[0]+brushX), \
atPoint[1] + int(originPoint[1]+brushY), \
*brushColours, 0, " "]
if isLeftDown or isRightDown:
dispatchFn(eventDc, False, patch); dispatchFn(eventDc, True, patch);
else:
dispatchFn(eventDc, True, patch)
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,38 @@
#!/usr/bin/env python3
#
# MiRCARTToolFill.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
from MiRCARTTool import MiRCARTTool
class MiRCARTToolFill(MiRCARTTool):
"""XXX"""
name = "Fill"
#
# onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc): XXX
def onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc):
pointStack = [list(atPoint)]; pointsDone = [];
testColour = self.parentCanvas.canvasMap[atPoint[1]][atPoint[0]][0:2]
if isLeftDown or isRightDown:
if isRightDown:
brushColours = [brushColours[1], brushColours[0]]
while len(pointStack) > 0:
point = pointStack.pop()
pointCell = self.parentCanvas.canvasMap[point[1]][point[0]]
if pointCell[0:2] == testColour:
if not point in pointsDone:
dispatchFn(eventDc, False, [*point, \
brushColours[0], brushColours[0], 0, " "])
if point[0] > 0:
pointStack.append([point[0] - 1, point[1]])
if point[0] < (self.parentCanvas.canvasSize[0] - 1):
pointStack.append([point[0] + 1, point[1]])
if point[1] > 0:
pointStack.append([point[0], point[1] - 1])
if point[1] < (self.parentCanvas.canvasSize[1] - 1):
pointStack.append([point[0], point[1] + 1])
pointsDone += [point]
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,87 @@
#!/usr/bin/env python3
#
# MiRCARTToolLine.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
from MiRCARTTool import MiRCARTTool
class MiRCARTToolLine(MiRCARTTool):
"""XXX"""
name = "Line"
toolColours = toolOriginPoint = toolState = None
TS_NONE = 0
TS_ORIGIN = 1
# {{{ _pointDelta(self, a, b): XXX
def _pointDelta(self, a, b):
return [a2-a1 for a1, a2 in zip(a, b)]
# }}}
# {{{ _pointSwap(self, a, b): XXX
def _pointSwap(self, a, b):
return [b, a]
# }}}
# {{{ _getLine(self, brushColours, brushSize, eventDc, isCursor, originPoint, targetPoint, dispatchFn): XXX
def _getLine(self, brushColours, brushSize, eventDc, isCursor, originPoint, targetPoint, dispatchFn):
originPoint = originPoint.copy(); targetPoint = targetPoint.copy();
pointDelta = self._pointDelta(originPoint, targetPoint)
lineXSign = 1 if pointDelta[0] > 0 else -1;
lineYSign = 1 if pointDelta[1] > 0 else -1;
pointDelta = [abs(a) for a in pointDelta]
if pointDelta[0] > pointDelta[1]:
lineXX, lineXY, lineYX, lineYY = lineXSign, 0, 0, lineYSign
else:
pointDelta = [pointDelta[1], pointDelta[0]]
lineXX, lineXY, lineYX, lineYY = 0, lineYSign, lineXSign, 0
lineD = 2 * pointDelta[1] - pointDelta[0]; lineY = 0;
for lineX in range(pointDelta[0] + 1):
for brushStep in range(brushSize[0]):
patch = [ \
originPoint[0] + lineX*lineXX + lineY*lineYX + brushStep, \
originPoint[1] + lineX*lineXY + lineY*lineYY, \
*brushColours, 0, " "]
if isCursor:
dispatchFn(eventDc, False, patch); dispatchFn(eventDc, True, patch);
else:
dispatchFn(eventDc, True, patch)
if lineD > 0:
lineD -= pointDelta[0]; lineY += 1;
lineD += pointDelta[1]
# }}}
#
# onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc): XXX
def onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc):
brushColours = brushColours.copy()
if isLeftDown:
brushColours[1] = brushColours[0]
elif isRightDown:
brushColours[0] = brushColours[1]
else:
brushColours[1] = brushColours[0]
if self.toolState == self.TS_NONE:
if isLeftDown or isRightDown:
self.toolColours = brushColours
self.toolOriginPoint = list(atPoint)
self.toolState = self.TS_ORIGIN
dispatchFn(eventDc, True, [*atPoint, *brushColours, 0, " "])
elif self.toolState == self.TS_ORIGIN:
targetPoint = list(atPoint)
originPoint = self.toolOriginPoint
self._getLine(self.toolColours, brushSize, \
eventDc, isLeftDown or isRightDown, \
originPoint, targetPoint, dispatchFn)
if isLeftDown or isRightDown:
self.toolColours = None
self.toolOriginPoint = None
self.toolState = self.TS_NONE
# __init__(self, *args): initialisation method
def __init__(self, *args):
super().__init__(*args)
self.toolColours = None
self.toolOriginPoint = None
self.toolState = self.TS_NONE
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,34 @@
#!/usr/bin/env python3
#
# MiRCARTToolRect.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
from MiRCARTTool import MiRCARTTool
class MiRCARTToolRect(MiRCARTTool):
"""XXX"""
name = "Rectangle"
#
# onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc): XXX
def onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc):
brushColours = brushColours.copy()
if isLeftDown:
brushColours[1] = brushColours[0]
elif isRightDown:
brushColours[0] = brushColours[1]
else:
brushColours[1] = brushColours[0]
brushSize = brushSize.copy()
if brushSize[0] > 1:
brushSize[0] *= 2
for brushRow in range(brushSize[1]):
for brushCol in range(brushSize[0]):
patch = [atPoint[0] + brushCol, atPoint[1] + brushRow, *brushColours, 0, " "]
if isLeftDown or isRightDown:
dispatchFn(eventDc, False, patch); dispatchFn(eventDc, True, patch);
else:
dispatchFn(eventDc, True, patch)
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -0,0 +1,111 @@
#!/usr/bin/env python3
#
# MiRCARTToolSelect.py -- XXX
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
#
from MiRCARTTool import MiRCARTTool
class MiRCARTToolSelect(MiRCARTTool):
"""XXX"""
toolColours = toolRect = toolState = None
toolLastAtPoint = None
toolSelectMap = None
srcRect = None
TS_NONE = 0
TS_ORIGIN = 1
TS_TARGET = 2
# {{{ _drawSelectRect(self, rect, dispatchFn, eventDc): XXX
def _drawSelectRect(self, rect, dispatchFn, eventDc):
rectFrame = [ \
[rect[0][0]-1, rect[0][1]-1], \
[rect[1][0]+1, rect[1][1]+1]]
if rectFrame[0][0] > rectFrame[1][0]:
rectFrame[0][0], rectFrame[1][0] = \
rectFrame[1][0], rectFrame[0][0]
if rectFrame[0][1] > rectFrame[1][1]:
rectFrame[0][1], rectFrame[1][1] = \
rectFrame[1][1], rectFrame[0][1]
curColours = [0, 0]
for rectX in range(rectFrame[0][0], rectFrame[1][0]+1):
if curColours == [0, 0]:
curColours = [1, 1]
else:
curColours = [0, 0]
dispatchFn(eventDc, True, \
[rectX, rectFrame[0][1], *curColours, 0, " "])
dispatchFn(eventDc, True, \
[rectX, rectFrame[1][1], *curColours, 0, " "])
for rectY in range(rectFrame[0][1], rectFrame[1][1]+1):
if curColours == [0, 0]:
curColours = [1, 1]
else:
curColours = [0, 0]
dispatchFn(eventDc, True, \
[rectFrame[0][0], rectY, *curColours, 0, " "])
dispatchFn(eventDc, True, \
[rectFrame[1][0], rectY, *curColours, 0, " "])
# }}}
#
# onSelectEvent(self, event, atPoint, selectRect, brushColours, brushSize, isLeftDown, isRightDown, dispatchFn, eventDc): XXX
def onSelectEvent(self, event, atPoint, selectRect, brushColours, brushSize, isLeftDown, isRightDown, dispatchFn, eventDc):
pass
#
# onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc): XXX
def onMouseEvent(self, event, atPoint, brushColours, brushSize, isDragging, isLeftDown, isRightDown, dispatchFn, eventDc):
if self.toolState == self.TS_NONE:
if isLeftDown or isRightDown:
self.toolColours = [0, 1]
self.toolRect = [list(atPoint), []]
self.toolState = self.TS_ORIGIN
else:
dispatchFn(eventDc, True, \
[*atPoint, *brushColours, 0, " "])
elif self.toolState == self.TS_ORIGIN:
self.toolRect[1] = list(atPoint)
if isLeftDown or isRightDown:
if self.toolRect[0][0] > self.toolRect[1][0]:
self.toolRect[0][0], self.toolRect[1][0] = \
self.toolRect[1][0], self.toolRect[0][0]
if self.toolRect[0][1] > self.toolRect[1][1]:
self.toolRect[0][1], self.toolRect[1][1] = \
self.toolRect[1][1], self.toolRect[0][1]
self.srcRect = self.toolRect[0]
self.toolLastAtPoint = list(atPoint)
self.toolState = self.TS_TARGET
self.toolSelectMap = []
for numRow in range((self.toolRect[1][1] - self.toolRect[0][1]) + 1):
self.toolSelectMap.append([])
for numCol in range((self.toolRect[1][0] - self.toolRect[0][0]) + 1):
rectY = self.toolRect[0][1] + numRow
rectX = self.toolRect[0][0] + numCol
self.toolSelectMap[numRow].append( \
self.parentCanvas.canvasMap[rectY][rectX])
self._drawSelectRect(self.toolRect, dispatchFn, eventDc)
elif self.toolState == self.TS_TARGET:
if isRightDown:
self.onSelectEvent(event, atPoint, self.toolRect, \
brushColours, brushSize, isLeftDown, isRightDown, \
dispatchFn, eventDc)
self.toolColours = None
self.toolRect = None
self.toolState = self.TS_NONE
else:
self.onSelectEvent(event, atPoint, self.toolRect, \
brushColours, brushSize, isLeftDown, isRightDown, \
dispatchFn, eventDc)
# __init__(self, *args): initialisation method
def __init__(self, *args):
super().__init__(*args)
self.toolColours = None
self.toolRect = None
self.toolState = self.TS_NONE
self.toolLastAtPoint = None
self.toolSelectMap = None
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

Some files were not shown because too many files have changed in this diff Show More