Replaces & merges MiRCART-{nw,python,www} w/ original MiRCART as of Thu Jul 5 2018.
2
.gitattributes
vendored
@ -1,2 +0,0 @@
|
||||
MiRCART-cordoba/* linguist-vendored
|
||||
MiRCART-nw/* linguist-vendored
|
9
.gitignore
vendored
@ -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
|
||||
|
@ -1 +0,0 @@
|
||||
../assets/text/LICENCE.asdf
|
@ -1,3 +0,0 @@
|
||||
@echo off
|
||||
start nw.exe .
|
||||
rem vim:fileformat=dos
|
@ -1 +0,0 @@
|
||||
../assets
|
@ -1 +0,0 @@
|
||||
../assets/shell/deploy-nw.sh
|
@ -1 +0,0 @@
|
||||
../assets/html/index.html
|
@ -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
|
5
MiRCART-nw/package-lock.json
generated
@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "MiRCART",
|
||||
"version": "1.1.6",
|
||||
"lockfileVersion": 1
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
3
MiRCART-python/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
MiRCARTImgurApiKey.py
|
||||
__pycache__/
|
||||
*.sw[op]
|
@ -1 +0,0 @@
|
||||
../assets/text/LICENCE.MIT
|
@ -1 +0,0 @@
|
||||
../assets/text/LICENCE.asdf
|
@ -1 +0,0 @@
|
||||
../assets
|
@ -1 +0,0 @@
|
||||
../assets/shell/deploy-www.sh
|
@ -1 +0,0 @@
|
||||
../assets/html/index.html
|
31
MiRCART.py
Executable 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
|
@ -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
|
||||
*/
|
@ -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
|
||||
*/
|
@ -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
|
||||
*/
|
@ -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
|
||||
*/
|
Before Width: | Height: | Size: 1.1 MiB |
@ -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
|
||||
<Alt> + <LMB> on canvas Fill brush with sampled color
|
||||
<Alt> + <Shift> + <LMB> on canvas Copy canvas to brush
|
||||
<Ctrl> + <LMB> on brush Erase brush cell
|
||||
<Ctrl> + <LMB> on canvas Draw with background color
|
||||
<Shift> + <LMB> on canvas Draw line from last position
|
||||
<Shift> + <LMB> on character box Switch to next character set
|
||||
<Shift> + <LMB> on stored brush Delete stored brush
|
||||
<LMB> on brush Fill brush cell
|
||||
<RMB> on brush Erase brush cell
|
||||
<RMB> 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
|
||||
-->
|
@ -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
After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.5 KiB |
BIN
assets/images/toolCircle.png
Normal file
After Width: | Height: | Size: 360 B |
BIN
assets/images/toolClone.png
Normal file
After Width: | Height: | Size: 227 B |
BIN
assets/images/toolDecrBrushH.png
Normal file
After Width: | Height: | Size: 271 B |
BIN
assets/images/toolDecrBrushHW.png
Normal file
After Width: | Height: | Size: 277 B |
BIN
assets/images/toolDecrBrushW.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
assets/images/toolDecrCanvasH.png
Normal file
After Width: | Height: | Size: 265 B |
BIN
assets/images/toolDecrCanvasHW.png
Normal file
After Width: | Height: | Size: 289 B |
BIN
assets/images/toolDecrCanvasW.png
Normal file
After Width: | Height: | Size: 249 B |
BIN
assets/images/toolFill.png
Normal file
After Width: | Height: | Size: 527 B |
BIN
assets/images/toolIncrBrushH.png
Normal file
After Width: | Height: | Size: 236 B |
BIN
assets/images/toolIncrBrushHW.png
Normal file
After Width: | Height: | Size: 290 B |
BIN
assets/images/toolIncrBrushW.png
Normal file
After Width: | Height: | Size: 232 B |
BIN
assets/images/toolIncrCanvasH.png
Normal file
After Width: | Height: | Size: 246 B |
BIN
assets/images/toolIncrCanvasHW.png
Normal file
After Width: | Height: | Size: 282 B |
BIN
assets/images/toolIncrCanvasW.png
Normal file
After Width: | Height: | Size: 236 B |
BIN
assets/images/toolLine.png
Normal file
After Width: | Height: | Size: 371 B |
BIN
assets/images/toolMove.png
Normal file
After Width: | Height: | Size: 213 B |
BIN
assets/images/toolRect.png
Normal file
After Width: | Height: | Size: 220 B |
BIN
assets/images/toolText.png
Normal file
After Width: | Height: | Size: 306 B |
@ -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()
|
@ -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
|
||||
|
||||
})()
|
||||
|
||||
|
@ -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
|
||||
}
|
294
assets/js/gfx.js
@ -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
|
||||
|
||||
})()
|
||||
|
148
assets/js/lex.js
@ -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 == " " ? " " : this.char || " "
|
||||
}
|
||||
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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
})()
|
@ -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
|
||||
|
||||
})()
|
@ -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
|
||||
|
||||
})()
|
259
assets/js/ui/controls.js
vendored
@ -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
|
||||
})()
|
@ -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]
|
||||
}
|
@ -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
|
||||
|
||||
})()
|
@ -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
|
||||
|
||||
})()
|
@ -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) }
|
||||
}
|
||||
})
|
@ -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,
|
||||
}
|
||||
|
||||
})()
|
@ -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,
|
||||
}
|
||||
})()
|
@ -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);
|
||||
}
|
@ -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
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
157
libcanvas/MiRCARTCanvasBackend.py
Normal 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
|
111
libcanvas/MiRCARTCanvasExportStore.py
Normal 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
|
335
libcanvas/MiRCARTCanvasInterface.py
Normal 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( \
|
||||
"253ce2f0a45140ee0a44ca99aa49260", \
|
||||
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
|
79
libcanvas/MiRCARTCanvasJournal.py
Normal 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
|
29
libcanvas/MiRCARTColours.py
Normal 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
@ -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
|
169
libgui/MiRCARTGeneralFrame.py
Normal 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
@ -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
|
38
libtools/MiRCARTToolCircle.py
Normal 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
|
38
libtools/MiRCARTToolFill.py
Normal 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
|
87
libtools/MiRCARTToolLine.py
Normal 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
|
34
libtools/MiRCARTToolRect.py
Normal 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
|
111
libtools/MiRCARTToolSelect.py
Normal 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
|