633 lines
16 KiB
JavaScript
633 lines
16 KiB
JavaScript
|
|
var $menus = $(E("div")).addClass("jspaint-menus").prependTo($V);
|
|
var selecting_menus = false;
|
|
var ____________________________ = "A HORIZONTAL RULE / DIVIDER";
|
|
|
|
function $FormWindow(title){
|
|
var $w = new $Window();
|
|
|
|
$w.title(title);
|
|
$w.$form = $form = $(E("form")).appendTo($w.$content);
|
|
$w.$form_left = $(E("div")).appendTo($w.$form);
|
|
$w.$form_right = $(E("div")).appendTo($w.$form).addClass("jspaint-button-group");
|
|
$w.$form.addClass("jspaint-horizontal").css({display: "flex"});
|
|
|
|
$w.$Button = function(label, action){
|
|
var $b = $(E("button")).appendTo($w.$form_right).text(label);
|
|
$b.on("click", function(e){
|
|
// prevent the form from submitting
|
|
e.preventDefault();
|
|
|
|
action();
|
|
});
|
|
|
|
// this should really not be needed @TODO
|
|
$b.addClass("jspaint-button jspaint-window-button");
|
|
|
|
return $b;
|
|
};
|
|
|
|
return $w;
|
|
};
|
|
|
|
var image_attributes = function(){
|
|
if(image_attributes.$window){
|
|
image_attributes.$window.close();
|
|
}
|
|
var $w = image_attributes.$window = new $FormWindow("Attributes");
|
|
|
|
var $form_left = $w.$form_left;
|
|
var $form_right = $w.$form_right;
|
|
|
|
// Information
|
|
|
|
var table = {
|
|
"File last saved": "Not available",
|
|
"Size on disk": "Not available",
|
|
"Resolution": "72 x 72 dots per inch",
|
|
};
|
|
var $table = $(E("table")).appendTo($form_left);
|
|
for(var k in table){
|
|
var $tr = $(E("tr")).appendTo($table);
|
|
var $key = $(E("td")).appendTo($tr).text(k + ":");
|
|
var $value = $(E("td")).appendTo($tr).text(table[k]);
|
|
}
|
|
|
|
// Dimensions
|
|
|
|
var unit_sizes_in_px = {px: 1, in: 72, cm: 28.3465};
|
|
var current_unit = image_attributes.unit = image_attributes.unit || "px";
|
|
var width_in_px = canvas.width;
|
|
var height_in_px = canvas.height;
|
|
|
|
var $width_label = $(E("label")).appendTo($form_left).text("Width:");
|
|
var $height_label = $(E("label")).appendTo($form_left).text("Height:");
|
|
var $width = $(E("input")).appendTo($width_label);
|
|
var $height = $(E("input")).appendTo($height_label);
|
|
$([$width[0], $height[0]])
|
|
.css({width: "40px"})
|
|
.on("change keyup keydown keypress mousedown mousemove paste drop", function(){
|
|
if($(this).is($width)){
|
|
width_in_px = $width.val() * unit_sizes_in_px[current_unit];
|
|
}
|
|
if($(this).is($height)){
|
|
height_in_px = $height.val() * unit_sizes_in_px[current_unit];
|
|
}
|
|
});
|
|
|
|
// Fieldsets
|
|
|
|
var $units = $(E("fieldset")).appendTo($form_left).append('<legend>Transparency</legend>');
|
|
$units.append('<label><input type="radio" name="units" value="in">Inches</label>');
|
|
$units.append('<label><input type="radio" name="units" value="cm">Cm</label>');
|
|
$units.append('<label><input type="radio" name="units" value="px">Pixels</label>');
|
|
$units.find("[value=" + current_unit + "]").attr({checked: true});
|
|
$units.on("change", function(){
|
|
var new_unit = $units.find(":checked").val();
|
|
$width.val(width_in_px / unit_sizes_in_px[new_unit]);
|
|
$height.val(height_in_px / unit_sizes_in_px[new_unit]);
|
|
current_unit = new_unit;
|
|
}).triggerHandler("change");
|
|
|
|
var $transparency = $(E("fieldset")).appendTo($form_left).append('<legend>Transparency</legend>');
|
|
$transparency.append('<label><input type="radio" name="transparency" value="transparent">Transparent</label>');
|
|
$transparency.append('<label><input type="radio" name="transparency" value="opaque">Opaque</label>');
|
|
$transparency.find("[value=" + (transparency ? "transparent" : "opaque") + "]").attr({checked: true});
|
|
|
|
// Buttons on the right
|
|
|
|
$w.$Button("Okay", function(){
|
|
var to = $transparency.find(":checked").val();
|
|
var unit = $units.find(":checked").val();
|
|
|
|
image_attributes.unit = unit;
|
|
transparency = (to == "transparent");
|
|
|
|
var unit_to_px = unit_sizes_in_px[unit];
|
|
var width = $width.val() * unit_to_px;
|
|
var height = $height.val() * unit_to_px;
|
|
$canvas.trigger("user-resized", [0, 0, ~~width, ~~height]);
|
|
|
|
image_attributes.$window.close();
|
|
});
|
|
|
|
$w.$Button("Cancel", function(){
|
|
image_attributes.$window.close();
|
|
});
|
|
|
|
$w.$Button("Default", function(){
|
|
width_in_px = default_canvas_width;
|
|
height_in_px = default_canvas_height;
|
|
$width.val(width_in_px / unit_sizes_in_px[current_unit]);
|
|
$height.val(height_in_px / unit_sizes_in_px[current_unit]);
|
|
});
|
|
|
|
// Reposition the window
|
|
|
|
image_attributes.$window.center();
|
|
};
|
|
|
|
var flip_and_rotate = function(){
|
|
var $w = new $FormWindow("Flip and Rotate");
|
|
|
|
var $fieldset = $(E("fieldset")).appendTo($w.$form_left);
|
|
$fieldset.append("<legend>Flip or rotate</legend>");
|
|
$fieldset.append("<label><input type='radio' name='flip-or-rotate' value='flip-horizontal' checked/>Flip horizontal</label>");
|
|
$fieldset.append("<label><input type='radio' name='flip-or-rotate' value='flip-vertical'/>Flip vertical</label>");
|
|
$fieldset.append("<label><input type='radio' name='flip-or-rotate' value='rotate-by-angle'/>Rotate by angle<div></div></label>");
|
|
|
|
var $rotate_by_angle = $fieldset.find("div")
|
|
$rotate_by_angle.css({paddingLeft: "30px"});
|
|
$rotate_by_angle.append("<label><input type='radio' name='rotate-by-angle' value='90' checked/>90°</label>");
|
|
$rotate_by_angle.append("<label><input type='radio' name='rotate-by-angle' value='180'/>180°</label>");
|
|
$rotate_by_angle.append("<label><input type='radio' name='rotate-by-angle' value='270'/>270°</label>");
|
|
$rotate_by_angle.find("input").attr({disabled: true});
|
|
|
|
$fieldset.find("input").on("change", function(){
|
|
$rotate_by_angle.find("input").attr({
|
|
disabled: ($fieldset.find("input[name='flip-or-rotate']:checked").val() !== 'rotate-by-angle')
|
|
});
|
|
});
|
|
|
|
$fieldset.find("label").css({display: "block"});
|
|
|
|
$w.$Button("Okay", function(){
|
|
$w.close();
|
|
}).on("mouseover", function(){
|
|
$(this).text("NOT OKAY");
|
|
});
|
|
$w.$Button("Cancel", function(){
|
|
$w.close();
|
|
});
|
|
|
|
$w.center();
|
|
};
|
|
|
|
var stretch_and_skew = function(){
|
|
var $w = new $FormWindow("Stretch and Skew");
|
|
|
|
var $fieldset_stretch = $(E("fieldset")).appendTo($w.$form_left);
|
|
$fieldset_stretch.append("<legend>Stretch</legend><table></table>");
|
|
var $fieldset_skew = $(E("fieldset")).appendTo($w.$form_left);
|
|
$fieldset_skew.append("<legend>Skew</legend><table></table>");
|
|
|
|
var $RowInput = function($table, img_src, label_text, default_value, label_unit){
|
|
var $tr = $(E("tr")).appendTo($table);
|
|
var $img = $(E("img")).attr({
|
|
src: "images/transforms/" + img_src + ".png"
|
|
}).css({
|
|
marginRight: "20px"
|
|
});
|
|
var $input = $(E("input")).attr({
|
|
value: default_value
|
|
}).css({
|
|
width: "40px"
|
|
});
|
|
$(E("td")).appendTo($tr).append($img);
|
|
$(E("td")).appendTo($tr).text(label_text);
|
|
$(E("td")).appendTo($tr).append($input);
|
|
$(E("td")).appendTo($tr).text(label_unit);
|
|
|
|
return $input;
|
|
};
|
|
|
|
var stretch_x = $RowInput($fieldset_stretch.find("table"), "stretch-x", "Horizontal:", 100, "%");
|
|
var stretch_y = $RowInput($fieldset_stretch.find("table"), "stretch-y", "Vertical:", 100, "%");
|
|
var skew_x = $RowInput($fieldset_skew.find("table"), "skew-x", "Horizontal:", 0, "Degrees");
|
|
var skew_y = $RowInput($fieldset_skew.find("table"), "skew-y", "Horizontal:", 0, "Degrees");
|
|
|
|
$w.$Button("Okay", function(){
|
|
$w.close();
|
|
}).on("mouseover", function(){
|
|
$(this).text("NOT OKAY");
|
|
});
|
|
$w.$Button("Cancel", function(){
|
|
$w.close();
|
|
});
|
|
|
|
$w.center();
|
|
};
|
|
|
|
var set_as_wallpaper_tiled = function(c){
|
|
c = c || canvas;
|
|
|
|
var wp = document.createElement("canvas");
|
|
wp.width = screen.width;
|
|
wp.height = screen.height;
|
|
var wpctx = wp.getContext("2d");
|
|
for(var x=0; x<wp.width; x+=c.width){
|
|
for(var y=0; y<wp.height; y+=c.height){
|
|
wpctx.drawImage(c, x, y);
|
|
}
|
|
}
|
|
|
|
set_as_wallpaper_centered(wp);
|
|
};
|
|
|
|
var set_as_wallpaper_centered = function(c){
|
|
c = c || canvas;
|
|
|
|
if(window.chrome && chrome.wallpaper){
|
|
chrome.wallpaper.setWallpaper({
|
|
url: c.toDataURL(),
|
|
layout: 'CENTER_CROPPED',
|
|
name: file_name,
|
|
}, function(){});
|
|
}else{
|
|
window.open(c.toDataURL());
|
|
}
|
|
};
|
|
|
|
var save_selection_to_file = function(){
|
|
if(selection && selection.canvas){
|
|
if(window.chrome && chrome.fileSystem && chrome.fileSystem.chooseEntry){
|
|
chrome.fileSystem.chooseEntry({
|
|
type: 'saveFile',
|
|
suggestedName: 'Selection',
|
|
accepts: [{mimeTypes: ["image/*"]}]
|
|
}, function(entry){
|
|
if(chrome.runtime.lastError){
|
|
return console.error(chrome.runtime.lastError.message);
|
|
}
|
|
entry.createWriter(function(file_writer){
|
|
file_writer.onwriteend = function(e){
|
|
if(this.error){
|
|
console.error(this.error + '\n\n\n@ ' + e);
|
|
}else{
|
|
console.log("Wrote selection to file!");
|
|
}
|
|
};
|
|
selection.canvas.toBlob(function(blob){
|
|
file_writer.write(blob);
|
|
});
|
|
});
|
|
});
|
|
}else{
|
|
window.open(selection.canvas.toDataURL());
|
|
}
|
|
}
|
|
};
|
|
|
|
var menus = {
|
|
"&File": [
|
|
{
|
|
item: "&New",
|
|
shortcut: "Ctrl+N",
|
|
action: file_new
|
|
},
|
|
{
|
|
item: "&Open",
|
|
shortcut: "Ctrl+O",
|
|
action: file_open
|
|
},
|
|
{
|
|
item: "&Save",
|
|
shortcut: "Ctrl+S",
|
|
action: file_save
|
|
},
|
|
{
|
|
item: "Save &As",
|
|
shortcut: "Ctrl+Shift+S",
|
|
action: file_save_as
|
|
},
|
|
____________________________,
|
|
{
|
|
item: "Print Pre&view"
|
|
},
|
|
{
|
|
item: "Page Se&tup"
|
|
},
|
|
{
|
|
item: "&Print",
|
|
shortcut: "Ctrl+P",
|
|
action: function(){print();}
|
|
},
|
|
____________________________,
|
|
{
|
|
item: "Set As &Wallpaper (Tiled)",
|
|
action: set_as_wallpaper_tiled
|
|
},
|
|
{
|
|
item: "Set As Wa&llpaper (Centered)",
|
|
action: set_as_wallpaper_centered
|
|
},
|
|
____________________________,
|
|
{
|
|
item: "Recent File",
|
|
disabled: true
|
|
},
|
|
____________________________,
|
|
{
|
|
item: "E&xit",
|
|
shortcut: "Alt+F4",
|
|
action: function(){
|
|
window.close();
|
|
}
|
|
}
|
|
],
|
|
"&Edit": [
|
|
{
|
|
item: "&Undo",
|
|
shortcut: "Ctrl+Z",
|
|
action: undo
|
|
},
|
|
{
|
|
item: "&Repeat",
|
|
shortcut: "F4",
|
|
action: redo,
|
|
disabled: true
|
|
},
|
|
____________________________,
|
|
{
|
|
item: "Cu&t",
|
|
shortcut: "Ctrl+X",
|
|
disabled: true
|
|
},
|
|
{
|
|
item: "&Copy",
|
|
shortcut: "Ctrl+C",
|
|
disabled: true
|
|
},
|
|
{
|
|
item: "&Paste",
|
|
shortcut: "Ctrl+V",
|
|
disabled: true
|
|
},
|
|
{
|
|
item: "C&lear Selection",
|
|
shortcut: "Del",
|
|
action: delete_selection,
|
|
disabled: true
|
|
},
|
|
{
|
|
item: "Select &All",
|
|
shortcut: "Ctrl+A",
|
|
action: select_all
|
|
},
|
|
____________________________,
|
|
{
|
|
item: "C&opy To...",
|
|
disabled: true,
|
|
action: save_selection_to_file
|
|
},
|
|
{
|
|
item: "Paste &From...",
|
|
action: paste_from
|
|
}
|
|
],
|
|
"&View": [
|
|
{
|
|
item: "&Tool Box",
|
|
shortcut: "Ctrl+T",
|
|
checkbox: {
|
|
toggle: function(){
|
|
return $toolbox.toggle().is(":visible");
|
|
}
|
|
}
|
|
},
|
|
{
|
|
item: "&Color Box",
|
|
shortcut: "Ctrl+L",
|
|
checkbox: {
|
|
toggle: function(){
|
|
return $colorbox.toggle().is(":visible");
|
|
}
|
|
}
|
|
},
|
|
{
|
|
item: "&Status Bar",
|
|
checkbox: {
|
|
toggle: function(){
|
|
return $status_area.toggle().is(":visible");
|
|
}
|
|
}
|
|
},
|
|
{
|
|
item: "T&ext Toolbar",
|
|
disabled: true,
|
|
checkbox: {}
|
|
},
|
|
____________________________,
|
|
{
|
|
item: "&Zoom",
|
|
submenu: [
|
|
{
|
|
item: "&Normal Size",
|
|
shorcut: "Ctrl+PgUp"
|
|
},
|
|
{
|
|
item: "&Large Size",
|
|
shorcut: "Ctrl+PgDn",
|
|
disabled: true
|
|
},
|
|
{
|
|
item: "C&ustom...",
|
|
disabled: true
|
|
},
|
|
____________________________,
|
|
{
|
|
item: "Show &Grid",
|
|
shorcut: "Ctrl+G",
|
|
checkbox: {},
|
|
disabled: true
|
|
},
|
|
{
|
|
item: "Show T&humbnail",
|
|
checkbox: {},
|
|
disabled: true
|
|
}
|
|
]
|
|
},
|
|
{
|
|
item: "&View Bitmap",
|
|
shortcut: "Ctrl+F",
|
|
action: view_bitmap
|
|
}
|
|
],
|
|
"&Image": [
|
|
{
|
|
item: "&Flip/Rotate",
|
|
shortcut: "Ctrl+R",
|
|
action: flip_and_rotate
|
|
},
|
|
{
|
|
item: "&Stretch/Skew",
|
|
shortcut: "Ctrl+W",
|
|
action: stretch_and_skew
|
|
},
|
|
{
|
|
item: "&Invert Colors",
|
|
shortcut: "Ctrl+I",
|
|
action: invert
|
|
},
|
|
{
|
|
item: "&Attributes...",
|
|
shortcut: "Ctrl+E",
|
|
action: image_attributes
|
|
},
|
|
{
|
|
item: "&Clear Image",
|
|
shortcut: "Ctrl+Shift+N",
|
|
action: clear
|
|
},
|
|
{
|
|
item: "&Draw Opaque",
|
|
checkbox: {}
|
|
}
|
|
],
|
|
"&Colors": [
|
|
{
|
|
item: "&Edit Colors...",
|
|
action: function(){
|
|
// Edit the last color cell that's been selected as the foreground color.
|
|
var $b = $colorbox.get_last_foreground_color_$button();
|
|
$b.trigger({type: "mousedown", ctrlKey: false, button: 0});
|
|
$b.find("input").trigger("click", "synthetic");
|
|
}
|
|
}
|
|
],
|
|
"&Help": [
|
|
{
|
|
item: "&Help Topics",
|
|
action: function(){
|
|
var $msgbox = new $Window();
|
|
$msgbox.title("Help Topics");
|
|
var url = "";
|
|
$msgbox.$content.html(
|
|
"<p style='padding:0;margin:5px'>Sorry, no help is available at this time.</p>" +
|
|
"<br>You can however try <a href='https://www.google.com/search?q=ms+paint+tutorials' target='_blank'>searching for tutorials</a> for MS Paint." +
|
|
"<br>There will be differences, but the basics are there."
|
|
).css({padding: "15px"});
|
|
$msgbox.center();
|
|
}
|
|
},
|
|
____________________________,
|
|
{
|
|
item: "&About Paint",
|
|
action: function(){
|
|
var $msgbox = new $Window();
|
|
$msgbox.title("About Paint");
|
|
$msgbox.$content.html(
|
|
"This is <a href='https://github.com/1j01/jspaint'>JS Paint</a>." +
|
|
"<br>" +
|
|
"Yeah.<br>"
|
|
).css({padding: "15px"});
|
|
$msgbox.center();
|
|
}
|
|
}
|
|
],
|
|
};
|
|
|
|
$.each(menus, function(menu_key, menu_items){
|
|
var _html = function(menu_key){
|
|
return menu_key.replace(/&(.)/, function(m){
|
|
return "<span class='jspaint-menu-hotkey'>" + m[1] + "</span>";
|
|
});
|
|
};
|
|
var _hotkey = function(menu_key){
|
|
return menu_key[menu_key.indexOf("&")+1].toUpperCase();
|
|
};
|
|
var this_click_opened_the_menu = false;
|
|
var $menu_container = $(E("div")).addClass("jspaint-menu-container").appendTo($menus);
|
|
var $menu_button = $(E("div")).addClass("jspaint-menu-button").appendTo($menu_container);
|
|
var $menu_popup = $(E("div")).addClass("jspaint-menu-popup").appendTo($menu_container);
|
|
var $menu_popup_table = $(E("table")).addClass("jspaint-menu-popup-table").appendTo($menu_popup);
|
|
$menu_popup.hide();
|
|
$menu_button.html(_html(menu_key));
|
|
$menu_button.on("mousedown mousemove", function(e){
|
|
if(e.type === "mousemove" && !selecting_menus){
|
|
return;
|
|
}
|
|
if(e.type === "mousedown"){
|
|
if(!$menu_button.hasClass("active")){
|
|
this_click_opened_the_menu = true;
|
|
}
|
|
}
|
|
|
|
$menus.find(".jspaint-menu-button").trigger("release");
|
|
|
|
$menu_button.addClass("active");
|
|
$menu_popup.show();
|
|
|
|
selecting_menus = true;
|
|
});
|
|
$menu_button.on("mouseup", function(e){
|
|
if(this_click_opened_the_menu){
|
|
this_click_opened_the_menu = false;
|
|
return;
|
|
}
|
|
if($menu_button.hasClass("active")){
|
|
$menus.find(".jspaint-menu-button").trigger("release");
|
|
}
|
|
});
|
|
$menu_button.on("release", function(e){
|
|
selecting_menus = false;
|
|
|
|
$menu_button.removeClass("active");
|
|
$menu_popup.hide();
|
|
});
|
|
$.map(menu_items, function(item){
|
|
var $row = $(E("tr")).addClass("jspaint-menu-row").appendTo($menu_popup_table)
|
|
if(item === ____________________________){
|
|
var $td = $(E("td")).attr({colspan: 4}).appendTo($row);
|
|
var $hr = $(E("hr")).addClass("jspaint-menu-hr").appendTo($td);
|
|
}else{
|
|
var $item = $row.addClass("jspaint-menu-item");
|
|
var $checkbox_area = $(E("td")).addClass("jspaint-menu-item-checkbox-area");
|
|
var $label = $(E("td")).addClass("jspaint-menu-item-label");
|
|
var $shortcut = $(E("td")).addClass("jspaint-menu-item-shortcut");
|
|
var $submenu_area = $(E("td")).addClass("jspaint-menu-item-submenu-area");
|
|
|
|
$item.append($checkbox_area, $label, $shortcut, $submenu_area);
|
|
|
|
$label.html(_html(item.item));
|
|
$shortcut.text(item.shortcut);
|
|
|
|
$item.attr("disabled", item.disabled);
|
|
|
|
if(item.checkbox){
|
|
$checkbox_area.text("✓");
|
|
}
|
|
|
|
if(item.submenu){
|
|
$submenu_area.text("▶");
|
|
var open_tid, close_tid;
|
|
$item.on("mouseover", function(){
|
|
if(open_tid){clearTimeout(open_tid);}
|
|
if(close_tid){clearTimeout(close_tid);}
|
|
open_tid = setTimeout(function(){
|
|
$submenu_area.text("▽");
|
|
}, 200);
|
|
});
|
|
$item.on("mouseout", function(){
|
|
if(open_tid){clearTimeout(open_tid);}
|
|
if(close_tid){clearTimeout(close_tid);}
|
|
open_tid = setTimeout(function(){
|
|
$submenu_area.text("▶");
|
|
}, 200);
|
|
});
|
|
}
|
|
|
|
$item.on("click", function(){
|
|
if(item.checkbox){
|
|
if(item.checkbox.toggle){
|
|
var check = item.checkbox.toggle();
|
|
$checkbox_area.text(check ? "✓" : "");
|
|
}
|
|
}else if(item.action){
|
|
$menus.find(".jspaint-menu-button").trigger("release");
|
|
item.action();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
$(window).on("keypress", function(e){
|
|
$menus.find(".jspaint-menu-button").trigger("release");
|
|
});
|
|
$(window).on("mousedown mouseup", function(e){
|
|
if(!$.contains($menus.get(0), e.target)){
|
|
$menus.find(".jspaint-menu-button").trigger("release");
|
|
}
|
|
});
|