kopia lustrzana https://github.com/backface/turtlestitch
Double click support for project dialogs
double clicking a project in the project dialog now performs the specified action for the dialog (open / save) on it.pull/3/merge
rodzic
977da0314c
commit
f21416527f
13
gui.js
13
gui.js
|
@ -68,7 +68,7 @@ sb, CommentMorph, CommandBlockMorph*/
|
||||||
|
|
||||||
// Global stuff ////////////////////////////////////////////////////////
|
// Global stuff ////////////////////////////////////////////////////////
|
||||||
|
|
||||||
modules.gui = '2013-April-19';
|
modules.gui = '2013-April-21';
|
||||||
|
|
||||||
// Declarations
|
// Declarations
|
||||||
|
|
||||||
|
@ -3738,7 +3738,9 @@ ProjectDialogMorph.prototype.setSource = function (source) {
|
||||||
this.projectList.length > 0 ?
|
this.projectList.length > 0 ?
|
||||||
function (element) {
|
function (element) {
|
||||||
return element.name;
|
return element.name;
|
||||||
} : null
|
} : null,
|
||||||
|
null,
|
||||||
|
function () {myself.ok(); }
|
||||||
);
|
);
|
||||||
|
|
||||||
this.fixListFieldItemColors();
|
this.fixListFieldItemColors();
|
||||||
|
@ -3754,6 +3756,7 @@ ProjectDialogMorph.prototype.setSource = function (source) {
|
||||||
this.listField.action = function (item) {
|
this.listField.action = function (item) {
|
||||||
var src, xml;
|
var src, xml;
|
||||||
|
|
||||||
|
if (item === undefined) {return; }
|
||||||
if (myself.nameField) {
|
if (myself.nameField) {
|
||||||
myself.nameField.setContents(item.name || '');
|
myself.nameField.setContents(item.name || '');
|
||||||
}
|
}
|
||||||
|
@ -3775,6 +3778,7 @@ ProjectDialogMorph.prototype.setSource = function (source) {
|
||||||
};
|
};
|
||||||
} else { // 'examples', 'cloud' is initialized elsewhere
|
} else { // 'examples', 'cloud' is initialized elsewhere
|
||||||
this.listField.action = function (item) {
|
this.listField.action = function (item) {
|
||||||
|
if (item === undefined) {return; }
|
||||||
if (myself.nameField) {
|
if (myself.nameField) {
|
||||||
myself.nameField.setContents(item.name || '');
|
myself.nameField.setContents(item.name || '');
|
||||||
}
|
}
|
||||||
|
@ -3852,7 +3856,9 @@ ProjectDialogMorph.prototype.installCloudProjectList = function (pl) {
|
||||||
'bold',
|
'bold',
|
||||||
function (proj) {return proj.Public === 'true'; }
|
function (proj) {return proj.Public === 'true'; }
|
||||||
]
|
]
|
||||||
]
|
],
|
||||||
|
null,
|
||||||
|
function () {myself.ok(); }
|
||||||
);
|
);
|
||||||
|
|
||||||
this.fixListFieldItemColors();
|
this.fixListFieldItemColors();
|
||||||
|
@ -3865,6 +3871,7 @@ ProjectDialogMorph.prototype.installCloudProjectList = function (pl) {
|
||||||
this.listField.drawRectBorder = InputFieldMorph.prototype.drawRectBorder;
|
this.listField.drawRectBorder = InputFieldMorph.prototype.drawRectBorder;
|
||||||
|
|
||||||
this.listField.action = function (item) {
|
this.listField.action = function (item) {
|
||||||
|
if (item === undefined) {return; }
|
||||||
if (myself.nameField) {
|
if (myself.nameField) {
|
||||||
myself.nameField.setContents(item.ProjectName || '');
|
myself.nameField.setContents(item.ProjectName || '');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1647,3 +1647,5 @@ ______
|
||||||
130421
|
130421
|
||||||
------
|
------
|
||||||
* using the percent character in variable names is now safe (fixes Github issue #65)
|
* using the percent character in variable names is now safe (fixes Github issue #65)
|
||||||
|
* Morphic: added Doubleclick support, example: inspectors
|
||||||
|
* GUI: Double clicking a project in the project dialog performs the dialog's action on it (open / save)
|
||||||
|
|
121
morphic.js
121
morphic.js
|
@ -147,6 +147,7 @@
|
||||||
III. yet to implement
|
III. yet to implement
|
||||||
---------------------
|
---------------------
|
||||||
- keyboard support for scroll frames and lists
|
- keyboard support for scroll frames and lists
|
||||||
|
- virtual keyboard support for Android and IE
|
||||||
|
|
||||||
|
|
||||||
IV. open issues
|
IV. open issues
|
||||||
|
@ -450,6 +451,7 @@
|
||||||
mouseDownRight
|
mouseDownRight
|
||||||
mouseClickLeft
|
mouseClickLeft
|
||||||
mouseClickRight
|
mouseClickRight
|
||||||
|
mouseDoubleClick
|
||||||
mouseEnter
|
mouseEnter
|
||||||
mouseLeave
|
mouseLeave
|
||||||
mouseEnterDragging
|
mouseEnterDragging
|
||||||
|
@ -1033,7 +1035,7 @@
|
||||||
/*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio,
|
/*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio,
|
||||||
FileList, getBlurredShadowSupport*/
|
FileList, getBlurredShadowSupport*/
|
||||||
|
|
||||||
var morphicVersion = '2013-April-19';
|
var morphicVersion = '2013-April-21';
|
||||||
var modules = {}; // keep track of additional loaded modules
|
var modules = {}; // keep track of additional loaded modules
|
||||||
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
|
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
|
||||||
|
|
||||||
|
@ -6161,7 +6163,7 @@ InspectorMorph.prototype.setTarget = function (target) {
|
||||||
};
|
};
|
||||||
|
|
||||||
InspectorMorph.prototype.buildPanes = function () {
|
InspectorMorph.prototype.buildPanes = function () {
|
||||||
var attribs = [], property, myself = this, ctrl, ev;
|
var attribs = [], property, myself = this, ctrl, ev, doubleClickAction;
|
||||||
|
|
||||||
// remove existing panes
|
// remove existing panes
|
||||||
this.children.forEach(function (m) {
|
this.children.forEach(function (m) {
|
||||||
|
@ -6194,6 +6196,20 @@ InspectorMorph.prototype.buildPanes = function () {
|
||||||
return typeof myself.target[prop] === 'function';
|
return typeof myself.target[prop] === 'function';
|
||||||
});
|
});
|
||||||
} // otherwise show all properties
|
} // otherwise show all properties
|
||||||
|
|
||||||
|
doubleClickAction = function () {
|
||||||
|
var world, inspector;
|
||||||
|
if (!isObject(myself.currentProperty)) {return; }
|
||||||
|
world = myself.world();
|
||||||
|
inspector = new InspectorMorph(
|
||||||
|
myself.currentProperty
|
||||||
|
);
|
||||||
|
inspector.setPosition(world.hand.position());
|
||||||
|
inspector.keepWithin(world);
|
||||||
|
world.add(inspector);
|
||||||
|
inspector.changed();
|
||||||
|
};
|
||||||
|
|
||||||
this.list = new ListMorph(
|
this.list = new ListMorph(
|
||||||
this.target instanceof Array ? attribs : attribs.sort(),
|
this.target instanceof Array ? attribs : attribs.sort(),
|
||||||
null, // label getter
|
null, // label getter
|
||||||
|
@ -6209,10 +6225,13 @@ InspectorMorph.prototype.buildPanes = function () {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
: null
|
: null,
|
||||||
|
doubleClickAction
|
||||||
);
|
);
|
||||||
|
|
||||||
this.list.action = function (selected) {
|
this.list.action = function (selected) {
|
||||||
var val, txt, cnts;
|
var val, txt, cnts;
|
||||||
|
if (selected === undefined) {return; }
|
||||||
val = myself.target[selected];
|
val = myself.target[selected];
|
||||||
myself.currentProperty = val;
|
myself.currentProperty = val;
|
||||||
if (val === null) {
|
if (val === null) {
|
||||||
|
@ -6228,6 +6247,7 @@ InspectorMorph.prototype.buildPanes = function () {
|
||||||
cnts.setReceiver(myself.target);
|
cnts.setReceiver(myself.target);
|
||||||
myself.detail.setContents(cnts);
|
myself.detail.setContents(cnts);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.list.hBar.alpha = 0.6;
|
this.list.hBar.alpha = 0.6;
|
||||||
this.list.vBar.alpha = 0.6;
|
this.list.vBar.alpha = 0.6;
|
||||||
this.list.contents.step = null;
|
this.list.contents.step = null;
|
||||||
|
@ -6609,7 +6629,8 @@ MenuMorph.prototype.addItem = function (
|
||||||
hint,
|
hint,
|
||||||
color,
|
color,
|
||||||
bold, // bool
|
bold, // bool
|
||||||
italic // bool
|
italic, // bool
|
||||||
|
doubleClickAction // optional, when used as list contents
|
||||||
) {
|
) {
|
||||||
/*
|
/*
|
||||||
labelString is normally a single-line string. But it can also be one
|
labelString is normally a single-line string. But it can also be one
|
||||||
|
@ -6625,7 +6646,8 @@ MenuMorph.prototype.addItem = function (
|
||||||
hint,
|
hint,
|
||||||
color,
|
color,
|
||||||
bold || false,
|
bold || false,
|
||||||
italic || false]);
|
italic || false,
|
||||||
|
doubleClickAction]);
|
||||||
};
|
};
|
||||||
|
|
||||||
MenuMorph.prototype.addLine = function (width) {
|
MenuMorph.prototype.addLine = function (width) {
|
||||||
|
@ -6713,7 +6735,8 @@ MenuMorph.prototype.drawNew = function () {
|
||||||
tuple[2], // bubble help hint
|
tuple[2], // bubble help hint
|
||||||
tuple[3], // color
|
tuple[3], // color
|
||||||
tuple[4], // bold
|
tuple[4], // bold
|
||||||
tuple[5] // italic
|
tuple[5], // italic
|
||||||
|
tuple[6] // doubleclick action
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (isLine) {
|
if (isLine) {
|
||||||
|
@ -7910,7 +7933,8 @@ function TriggerMorph(
|
||||||
hint,
|
hint,
|
||||||
labelColor,
|
labelColor,
|
||||||
labelBold,
|
labelBold,
|
||||||
labelItalic
|
labelItalic,
|
||||||
|
doubleClickAction
|
||||||
) {
|
) {
|
||||||
this.init(
|
this.init(
|
||||||
target,
|
target,
|
||||||
|
@ -7922,7 +7946,8 @@ function TriggerMorph(
|
||||||
hint,
|
hint,
|
||||||
labelColor,
|
labelColor,
|
||||||
labelBold,
|
labelBold,
|
||||||
labelItalic
|
labelItalic,
|
||||||
|
doubleClickAction
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7936,11 +7961,13 @@ TriggerMorph.prototype.init = function (
|
||||||
hint,
|
hint,
|
||||||
labelColor,
|
labelColor,
|
||||||
labelBold,
|
labelBold,
|
||||||
labelItalic
|
labelItalic,
|
||||||
|
doubleClickAction
|
||||||
) {
|
) {
|
||||||
// additional properties:
|
// additional properties:
|
||||||
this.target = target || null;
|
this.target = target || null;
|
||||||
this.action = action || null;
|
this.action = action || null;
|
||||||
|
this.doubleClickAction = doubleClickAction || null;
|
||||||
this.environment = environment || null;
|
this.environment = environment || null;
|
||||||
this.labelString = labelString || null;
|
this.labelString = labelString || null;
|
||||||
this.label = null;
|
this.label = null;
|
||||||
|
@ -8067,6 +8094,29 @@ TriggerMorph.prototype.trigger = function () {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TriggerMorph.prototype.triggerDoubleClick = function () {
|
||||||
|
// same as trigger() but use doubleClickAction instead of action property
|
||||||
|
// note that specifying a doubleClickAction is optional
|
||||||
|
if (!this.doubleClickAction) {return; }
|
||||||
|
if (typeof this.target === 'function') {
|
||||||
|
if (typeof this.doubleClickAction === 'function') {
|
||||||
|
this.target.call(
|
||||||
|
this.environment,
|
||||||
|
this.doubleClickAction.call(),
|
||||||
|
this
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.target.call(this.environment, this.doubleClickAction, this);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (typeof this.doubleClickAction === 'function') {
|
||||||
|
this.doubleClickAction.call(this.target);
|
||||||
|
} else { // assume it's a String
|
||||||
|
this.target[this.doubleClickAction]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// TriggerMorph events:
|
// TriggerMorph events:
|
||||||
|
|
||||||
TriggerMorph.prototype.mouseEnter = function () {
|
TriggerMorph.prototype.mouseEnter = function () {
|
||||||
|
@ -8096,6 +8146,10 @@ TriggerMorph.prototype.mouseClickLeft = function () {
|
||||||
this.trigger();
|
this.trigger();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TriggerMorph.prototype.mouseDoubleClick = function () {
|
||||||
|
this.triggerDoubleClick();
|
||||||
|
};
|
||||||
|
|
||||||
TriggerMorph.prototype.rootForGrab = function () {
|
TriggerMorph.prototype.rootForGrab = function () {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
@ -8147,7 +8201,8 @@ function MenuItemMorph(
|
||||||
hint,
|
hint,
|
||||||
color,
|
color,
|
||||||
bold,
|
bold,
|
||||||
italic
|
italic,
|
||||||
|
doubleClickAction // optional when used as list morph item
|
||||||
) {
|
) {
|
||||||
this.init(
|
this.init(
|
||||||
target,
|
target,
|
||||||
|
@ -8159,7 +8214,8 @@ function MenuItemMorph(
|
||||||
hint,
|
hint,
|
||||||
color,
|
color,
|
||||||
bold,
|
bold,
|
||||||
italic
|
italic,
|
||||||
|
doubleClickAction
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8859,7 +8915,7 @@ ListMorph.prototype = new ScrollFrameMorph();
|
||||||
ListMorph.prototype.constructor = ListMorph;
|
ListMorph.prototype.constructor = ListMorph;
|
||||||
ListMorph.uber = ScrollFrameMorph.prototype;
|
ListMorph.uber = ScrollFrameMorph.prototype;
|
||||||
|
|
||||||
function ListMorph(elements, labelGetter, format) {
|
function ListMorph(elements, labelGetter, format, doubleClickAction) {
|
||||||
/*
|
/*
|
||||||
passing a format is optional. If the format parameter is specified
|
passing a format is optional. If the format parameter is specified
|
||||||
it has to be of the following pattern:
|
it has to be of the following pattern:
|
||||||
|
@ -8891,11 +8947,17 @@ function ListMorph(elements, labelGetter, format) {
|
||||||
}
|
}
|
||||||
return element.toString();
|
return element.toString();
|
||||||
},
|
},
|
||||||
format || []
|
format || [],
|
||||||
|
doubleClickAction // optional callback
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ListMorph.prototype.init = function (elements, labelGetter, format) {
|
ListMorph.prototype.init = function (
|
||||||
|
elements,
|
||||||
|
labelGetter,
|
||||||
|
format,
|
||||||
|
doubleClickAction
|
||||||
|
) {
|
||||||
ListMorph.uber.init.call(this);
|
ListMorph.uber.init.call(this);
|
||||||
|
|
||||||
this.contents.acceptsDrops = false;
|
this.contents.acceptsDrops = false;
|
||||||
|
@ -8909,6 +8971,7 @@ ListMorph.prototype.init = function (elements, labelGetter, format) {
|
||||||
this.selected = null; // actual element currently selected
|
this.selected = null; // actual element currently selected
|
||||||
this.active = null; // menu item representing the selected element
|
this.active = null; // menu item representing the selected element
|
||||||
this.action = null;
|
this.action = null;
|
||||||
|
this.doubleClickAction = doubleClickAction || null;
|
||||||
this.acceptsDrops = false;
|
this.acceptsDrops = false;
|
||||||
this.buildListContents();
|
this.buildListContents();
|
||||||
};
|
};
|
||||||
|
@ -8948,7 +9011,8 @@ ListMorph.prototype.buildListContents = function () {
|
||||||
null, // hint
|
null, // hint
|
||||||
color,
|
color,
|
||||||
bold,
|
bold,
|
||||||
italic
|
italic,
|
||||||
|
myself.doubleClickAction
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
this.listContents.setPosition(this.contents.position());
|
this.listContents.setPosition(this.contents.position());
|
||||||
|
@ -9340,6 +9404,7 @@ HandMorph.prototype.drop = function () {
|
||||||
mouseDownRight
|
mouseDownRight
|
||||||
mouseClickLeft
|
mouseClickLeft
|
||||||
mouseClickRight
|
mouseClickRight
|
||||||
|
mouseDoubleClick
|
||||||
mouseEnter
|
mouseEnter
|
||||||
mouseLeave
|
mouseLeave
|
||||||
mouseEnterDragging
|
mouseEnterDragging
|
||||||
|
@ -9472,6 +9537,23 @@ HandMorph.prototype.processMouseUp = function () {
|
||||||
this.mouseButton = null;
|
this.mouseButton = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HandMorph.prototype.processDoubleClick = function () {
|
||||||
|
var morph = this.morphAtPointer();
|
||||||
|
|
||||||
|
this.destroyTemporaries();
|
||||||
|
if (this.children.length !== 0) {
|
||||||
|
this.drop();
|
||||||
|
} else {
|
||||||
|
while (morph && !morph.mouseDoubleClick) {
|
||||||
|
morph = morph.parent;
|
||||||
|
}
|
||||||
|
if (morph) {
|
||||||
|
morph.mouseDoubleClick(this.bounds.origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.mouseButton = null;
|
||||||
|
};
|
||||||
|
|
||||||
HandMorph.prototype.processMouseMove = function (event) {
|
HandMorph.prototype.processMouseMove = function (event) {
|
||||||
var pos,
|
var pos,
|
||||||
posInDocument = getDocumentPositionOf(this.world.worldCanvas),
|
posInDocument = getDocumentPositionOf(this.world.worldCanvas),
|
||||||
|
@ -10039,6 +10121,15 @@ WorldMorph.prototype.initEventListeners = function () {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
canvas.addEventListener(
|
||||||
|
"dblclick",
|
||||||
|
function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
myself.hand.processDoubleClick(event);
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
canvas.addEventListener(
|
canvas.addEventListener(
|
||||||
"touchend",
|
"touchend",
|
||||||
function (event) {
|
function (event) {
|
||||||
|
|
31
morphic.txt
31
morphic.txt
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
Copyright (C) 2012 by Jens Mönig
|
Copyright (C) 2012 by Jens Mönig
|
||||||
|
|
||||||
this documentation last changed: November 07, 2012
|
this documentation last changed: April 07, 2013
|
||||||
|
|
||||||
This file is part of Snap!.
|
This file is part of Snap!.
|
||||||
|
|
||||||
|
@ -148,6 +148,7 @@
|
||||||
III. yet to implement
|
III. yet to implement
|
||||||
---------------------
|
---------------------
|
||||||
- keyboard support for scroll frames and lists
|
- keyboard support for scroll frames and lists
|
||||||
|
- virtual keyboard support for Android and IE
|
||||||
|
|
||||||
|
|
||||||
IV. open issues
|
IV. open issues
|
||||||
|
@ -451,6 +452,7 @@
|
||||||
mouseDownRight
|
mouseDownRight
|
||||||
mouseClickLeft
|
mouseClickLeft
|
||||||
mouseClickRight
|
mouseClickRight
|
||||||
|
mouseDoubleClick
|
||||||
mouseEnter
|
mouseEnter
|
||||||
mouseLeave
|
mouseLeave
|
||||||
mouseEnterDragging
|
mouseEnterDragging
|
||||||
|
@ -579,13 +581,25 @@
|
||||||
Drops of image elements from outside the world canvas are dispatched as
|
Drops of image elements from outside the world canvas are dispatched as
|
||||||
|
|
||||||
droppedImage(aCanvas, name)
|
droppedImage(aCanvas, name)
|
||||||
|
droppedSVG(anImage, name)
|
||||||
|
|
||||||
events to interested Morphs at the mouse pointer. If you want you Morph
|
events to interested Morphs at the mouse pointer. If you want you Morph
|
||||||
to e.g. import outside images you can add the droppedImage() method to
|
to e.g. import outside images you can add the droppedImage() and / or the
|
||||||
it. The parameter passed to the event handles is a new offscreen
|
droppedSVG() methods to it. The parameter passed to the event handles is
|
||||||
canvas element representing a copy of the original image element which
|
a new offscreen canvas element representing a copy of the original image
|
||||||
can be directly used, e.g. by assigning it to another Morph's image
|
element which can be directly used, e.g. by assigning it to another
|
||||||
property.
|
Morph's image property. In the case of a dropped SVG it is an image
|
||||||
|
element (not a canvas), which has to be rasterized onto a canvas before
|
||||||
|
it can be used. The benefit of handling SVGs as image elements is that
|
||||||
|
rasterization can be deferred until the destination scale is known, taking
|
||||||
|
advantage of SVG's ability for smooth scaling. If instead SVGs are to be
|
||||||
|
rasterized right away, you can set the
|
||||||
|
|
||||||
|
MorphicPreferences.rasterizeSVGs
|
||||||
|
|
||||||
|
preference to <true>. In this case dropped SVGs also trigger the
|
||||||
|
droppedImage() event with a canvas containing a rasterized version of the
|
||||||
|
SVG.
|
||||||
|
|
||||||
The same applies to drops of audio or text files from outside the world
|
The same applies to drops of audio or text files from outside the world
|
||||||
canvas.
|
canvas.
|
||||||
|
@ -597,6 +611,11 @@
|
||||||
|
|
||||||
events to interested Morphs at the mouse pointer.
|
events to interested Morphs at the mouse pointer.
|
||||||
|
|
||||||
|
if none of the above content types can be determined, the file contents
|
||||||
|
is dispatched as an ArrayBuffer to interested Morphs:
|
||||||
|
|
||||||
|
droppedBinary(anArrayBuffer, name)
|
||||||
|
|
||||||
|
|
||||||
(e) keyboard events
|
(e) keyboard events
|
||||||
-------------------
|
-------------------
|
||||||
|
|
Ładowanie…
Reference in New Issue