This repository has been archived by the owner on Sep 6, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Show pixel info under the mouse when previewing image. #5944
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
b35c9e8
Implement cursor info tip showing image coordinates under the cursor.
RaymondLim b5602d6
Merge changes in master and resolve conflict in brackets.less.
RaymondLim 75d10da
Switch to custom cursor
RaymondLim 42a11cf
Adding cursor images from Larz.
RaymondLim 2c479a9
Remove the code that I accidently reintroduced when resolving the mer…
RaymondLim b371230
Prevent a possible divide-by-zero error and a minor coordinate alignm…
RaymondLim f08078b
Merge remote-tracking branch 'origin' into rlim/cursor-info-on-image
RaymondLim 3a38e61
New cursor images and minor tweak to cursor-info padding
larz0 e12d708
Temporarily hide scale sticker to show cursor info behind it.
RaymondLim 6bc2023
Use table to format the x and y coordinate values as suggested by Larz.
RaymondLim 20b2a82
Initialize _scale to 100 for every image load.
RaymondLim d58c351
Moving the initialization to the top of render function.
RaymondLim bac09cc
Merge remote-tracking branch 'origin' into rlim/cursor-info-on-image
RaymondLim 0e6dd73
Merge remote-tracking branch 'origin' into rlim/cursor-info-on-image
RaymondLim 627230e
Use cross guides instead of crosshair cursor.
RaymondLim 210739a
Fix some issues with mouse entering/exiting image scale sticker.
RaymondLim 160cedc
Adjust the color of guides with alpha value.
RaymondLim 0ca7e55
Remove the custom cursor files no longer needed.
RaymondLim 653890b
Remove the unused css rule.
RaymondLim 925997a
Made some changes for review feedback.
RaymondLim File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,7 @@ | |
|
||
|
||
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */ | ||
/*global define, $, Mustache */ | ||
/*global define, $, window, Mustache */ | ||
define(function (require, exports, module) { | ||
"use strict"; | ||
|
||
|
@@ -36,15 +36,19 @@ define(function (require, exports, module) { | |
StringUtils = require("utils/StringUtils"), | ||
FileSystem = require("filesystem/FileSystem"); | ||
|
||
var _naturalWidth = 0; | ||
var _naturalWidth = 0, | ||
_scale = 100, | ||
_scaleDivInfo = null; // coordinates of hidden scale sticker | ||
|
||
/** Update the scale element, i.e. on resize | ||
* @param {!string} currentWidth actual width of image in view | ||
*/ | ||
function _updateScale(currentWidth) { | ||
if (currentWidth < _naturalWidth) { | ||
var scale = Math.floor(currentWidth / _naturalWidth * 100); | ||
$("#img-scale").text(scale + "%") | ||
_scale = currentWidth / _naturalWidth * 100; | ||
$("#img-scale").text(Math.floor(_scale) + "%") | ||
// Keep the position of the image scale div relative to the image. | ||
.css("left", $("#img-preview").position().left + 5) | ||
.show(); | ||
} else { | ||
$("#img-scale").hide(); | ||
|
@@ -70,6 +74,200 @@ define(function (require, exports, module) { | |
} | ||
} | ||
|
||
/** | ||
* Check mouse entering/exiting the scale sticker. | ||
* Hide it when entering and show it again when exiting. | ||
* | ||
* @param {number} offsetX mouse offset from the left of the previewing image | ||
* @param {number} offsetY mouseoffset from the top of the previewing image | ||
*/ | ||
function _handleMouseEnterOrExitScaleSticker(offsetX, offsetY) { | ||
var imagePos = $("#img-preview").position(), | ||
scaleDivPos = $("#img-scale").position(), | ||
imgWidth = $("#img-preview").width(), | ||
imgHeight = $("#img-preview").height(), | ||
scaleDivLeft, | ||
scaleDivTop, | ||
scaleDivRight, | ||
scaleDivBottom; | ||
|
||
if (_scaleDivInfo) { | ||
scaleDivLeft = _scaleDivInfo.left; | ||
scaleDivTop = _scaleDivInfo.top; | ||
scaleDivRight = _scaleDivInfo.right; | ||
scaleDivBottom = _scaleDivInfo.bottom; | ||
|
||
if ((imgWidth + imagePos.left) < scaleDivRight) { | ||
scaleDivRight = imgWidth + imagePos.left; | ||
} | ||
|
||
if ((imgHeight + imagePos.top) < scaleDivBottom) { | ||
scaleDivBottom = imgHeight + imagePos.top; | ||
} | ||
|
||
} else { | ||
scaleDivLeft = scaleDivPos.left; | ||
scaleDivTop = scaleDivPos.top; | ||
scaleDivRight = $("#img-scale").width() + scaleDivLeft; | ||
scaleDivBottom = $("#img-scale").height() + scaleDivTop; | ||
} | ||
|
||
if (_scaleDivInfo) { | ||
// See whether the cursor is no longer inside the hidden scale div. | ||
// If so, show it again. | ||
if ((offsetX < scaleDivLeft || offsetX > scaleDivRight) || | ||
(offsetY < scaleDivTop || offsetY > scaleDivBottom)) { | ||
_scaleDivInfo = null; | ||
$("#img-scale").show(); | ||
} | ||
} else if ((offsetX >= scaleDivLeft && offsetX <= scaleDivRight) && | ||
(offsetY >= scaleDivTop && offsetY <= scaleDivBottom)) { | ||
// Handle mouse inside image scale div. | ||
// But hide it only if the pixel under mouse is also in the image. | ||
if (offsetX < (imagePos.left + imgWidth) && | ||
offsetY < (imagePos.top + imgHeight)) { | ||
// Remember image scale div coordinates before hiding it. | ||
_scaleDivInfo = {left: scaleDivPos.left, | ||
top: scaleDivPos.top, | ||
right: scaleDivRight, | ||
bottom: scaleDivBottom}; | ||
$("#img-scale").hide(); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Show image coordinates under the mouse cursor | ||
* | ||
* @param {MouseEvent} e mouse move event | ||
*/ | ||
function _showImageTip(e) { | ||
// Don't show image tip if _scale is close to zero. | ||
// since we won't have enough room to show tip anyway. | ||
if (Math.floor(_scale) === 0) { | ||
return; | ||
} | ||
|
||
var x = Math.floor(e.offsetX * 100 / _scale), | ||
y = Math.floor(e.offsetY * 100 / _scale), | ||
$target = $(e.target), | ||
targetPos = $target.position(), | ||
tipPos = $("#img-tip").position(), | ||
imagePos = $("#img-preview").position(), | ||
scaleDivPos = $("#img-scale").position(), | ||
left = e.offsetX + imagePos.left, | ||
top = e.offsetY + imagePos.top, | ||
width = $("#img-preview").width(), | ||
height = $("#img-preview").height(), | ||
windowWidth = $(window).width(), | ||
fourDigitImageWidth = _naturalWidth.toString().length === 4, | ||
infoWidth1 = 112, // info div width 96px + vertical toolbar width 16px | ||
infoWidth2 = 120, // info div width 104px (for 4-digit image width) + vertical toolbar width 16px | ||
tipOffsetX = 10, // adjustment for info div left from x coordinate of cursor | ||
tipOffsetY = -54, // adjustment for info div top from y coordinate of cursor | ||
tipMinusOffsetX1 = -82, // for less than 4-digit image width | ||
tipMinusOffsetX2 = -90; // for 4-digit image width | ||
|
||
// Adjust left, top, x and y based on which element contains the cursor. | ||
// Return if the target element is no longer available as in the case of | ||
// a vertical guide that has its left equals to zero. | ||
if ($target.is(".img-guide")) { | ||
if ($target.is("#vert-guide")) { | ||
if (targetPos.left === 0) { | ||
return; | ||
} | ||
left = targetPos.left; | ||
x = Math.floor(left * 100 / _scale); | ||
} else { | ||
if (targetPos.top === 0) { | ||
return; | ||
} | ||
top = targetPos.top; | ||
y = Math.floor(top * 100 / _scale); | ||
} | ||
} else if (!$target.is("#img-preview")) { | ||
if ($target.is("#img-scale")) { | ||
left = scaleDivPos.left + e.offsetX; | ||
top = scaleDivPos.top + e.offsetY; | ||
x = Math.floor(left * 100 / _scale); | ||
y = Math.floor(top * 100 / _scale); | ||
} else if (tipPos.left && tipPos.top) { | ||
// Cursor must be inside the image tip. | ||
left = tipPos.left + e.offsetX; | ||
top = tipPos.top + e.offsetY; | ||
x = Math.floor(left * 100 / _scale); | ||
y = Math.floor(top * 100 / _scale); | ||
} else { | ||
return; | ||
} | ||
} | ||
|
||
_handleMouseEnterOrExitScaleSticker(left, top); | ||
if ($(e.target).is("#img-scale")) { | ||
// If we're in the scale sticker, then just return. | ||
return; | ||
} | ||
|
||
// Check whether to show the image tip on the left. | ||
if ((e.pageX + infoWidth1) > windowWidth || | ||
(fourDigitImageWidth && (e.pageX + infoWidth2) > windowWidth)) { | ||
tipOffsetX = fourDigitImageWidth ? tipMinusOffsetX2 : tipMinusOffsetX1; | ||
} | ||
|
||
// For some reason we're getting -1 for e.offset when hovering over the very | ||
// first pixel of a scaled image. So adjust x to 0 if it is negative. | ||
if (x < 0) { | ||
x = 0; | ||
} | ||
|
||
$("#x-value").text(x + "px"); | ||
$("#y-value").text(y + "px"); | ||
|
||
$("#img-tip").css({ | ||
left: left + tipOffsetX, | ||
top: top + tipOffsetY | ||
}).show(); | ||
|
||
$("#horiz-guide").css({ | ||
left: imagePos.left, | ||
top: top, | ||
width: width - 1 | ||
}).show(); | ||
|
||
$("#vert-guide").css({ | ||
left: left, | ||
top: imagePos.top, | ||
height: height - 1 | ||
}).show(); | ||
} | ||
|
||
/** | ||
* Show image coordinates under the mouse cursor | ||
* | ||
* @param {MouseEvent} e mouse leave event | ||
*/ | ||
function _hideImageTip(e) { | ||
var $target = $(e.target), | ||
targetPos = $target.position(), | ||
imagePos = $("#img-preview").position(), | ||
right = imagePos.left + $("#img-preview").width(), | ||
bottom = imagePos.top + $("#img-preview").height(), | ||
offsetX = e.offsetX, | ||
offsetY = e.offsetY; | ||
|
||
if ($target.is(".img-guide")) { | ||
offsetX = targetPos.left + offsetX; | ||
offsetY = targetPos.top + offsetY; | ||
} | ||
|
||
// Hide image tip and guides only if the cursor is outside of the image. | ||
if (offsetX < imagePos.left || offsetX >= right || | ||
offsetY < imagePos.top || offsetY >= bottom) { | ||
$("#img-tip").hide(); | ||
$(".img-guide").hide(); | ||
} | ||
} | ||
|
||
/** | ||
* creates a DOM node to place in the editor-holder | ||
* in order to display an image. | ||
|
@@ -87,15 +285,21 @@ define(function (require, exports, module) { | |
function _removeListeners() { | ||
$(PanelManager).off("editorAreaResize", _onEditorAreaResize); | ||
$(DocumentManager).off("fileNameChange", _onFileNameChange); | ||
$("#img").off("mousemove", "#img-preview, #img-scale, #img-tip, .img-guide", _showImageTip) | ||
.off("mouseleave", "#img-preview, #img-scale, #img-tip, .img-guide", _hideImageTip); | ||
} | ||
|
||
/** Perform decorations on the view that require loading the image in the browser, | ||
* i.e. getting actual and natural width and height andplacing the scale sticker | ||
* @param {!string} fullPath path to the image file | ||
/** | ||
* Perform decorations on the view that require loading the image in the browser, | ||
* i.e. getting actual and natural width and height andplacing the scale sticker | ||
* @param {!string} fullPath path to the image file | ||
*/ | ||
function render(fullPath) { | ||
var relPath = ProjectManager.makeProjectRelativeIfPossible(fullPath); | ||
|
||
_scale = 100; // initialize to 100 | ||
_scaleDivInfo = null; | ||
|
||
$("#img-path").text(relPath) | ||
.attr("title", relPath); | ||
$("#img-preview").on("load", function () { | ||
|
@@ -104,6 +308,7 @@ define(function (require, exports, module) { | |
var dimensionString = _naturalWidth + " × " + this.naturalHeight + " " + Strings.UNIT_PIXELS; | ||
// get image size | ||
var file = FileSystem.getFileForPath(fullPath); | ||
var minimumPixels = 20; // for showing crosshair cursor | ||
file.stat(function (err, stat) { | ||
if (err) { | ||
$("#img-data").html(dimensionString); | ||
|
@@ -125,9 +330,25 @@ define(function (require, exports, module) { | |
// listen to removal to stop listening to resize events | ||
$(EditorManager).on("removeCustomViewer", _removeListeners); | ||
$(DocumentManager).on("fileNameChange", _onFileNameChange); | ||
|
||
$("#img-tip").hide(); | ||
$(".img-guide").hide(); | ||
$("#img").on("mousemove", "#img-preview, #img-scale, #img-tip, .img-guide", _showImageTip) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like to see all events handled in a single function. That's fenitely an improvement that makes this code more maintainable. |
||
.on("mouseleave", "#img-preview, #img-scale, #img-tip, .img-guide", _hideImageTip); | ||
|
||
_updateScale($(this).width()); | ||
minimumPixels = Math.floor(minimumPixels * 100 / _scale); | ||
|
||
// If the image size is too narrow in width or height, then | ||
// show the crosshair cursor since guides are almost invisible | ||
// in narrow images. | ||
if (this.naturalWidth < minimumPixels || this.naturalHeight < minimumPixels) { | ||
$("#img-preview").css("cursor", "crosshair"); | ||
$(".img-guide").css("cursor", "crosshair"); | ||
} | ||
}); | ||
} | ||
|
||
exports.getCustomViewHolder = getCustomViewHolder; | ||
exports.render = render; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should reset the state of this var in render(), as done for _scale. When opening 2 scaled images consecutivley then the mouse can move over the scale and it will not be hidden immediately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Fixed.