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
jmoenig 2013-04-21 20:40:24 +02:00
rodzic 977da0314c
commit f21416527f
4 zmienionych plików z 944 dodań i 825 usunięć

13
gui.js
Wyświetl plik

@ -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 || '');
} }

Wyświetl plik

@ -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)

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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
------------------- -------------------