mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-01 11:12:42 +01:00
When an image is too wide in Pholio, scale it down
Summary: Currently, if an image is too wide for the viewport, we freak out. Instead, scale it down. This means we must also scale down all the rectangles on it, which is why this is tricky. However, all the draw/load separation has made it reasonably straightforward. We'll possibly need to add some kind of "view full size" thing. I'm planning to add an element which shows "85%" or whatever if it's currently scaled. Test Plan: Before: {F33607} After: {F33608} Reviewers: chad, ljalonen Reviewed By: chad CC: aran Differential Revision: https://secure.phabricator.com/D5088
This commit is contained in:
parent
8641ef3948
commit
26f8e76ee2
5 changed files with 109 additions and 56 deletions
5
externals/javelinjs/src/core/Event.js
vendored
5
externals/javelinjs/src/core/Event.js
vendored
|
@ -142,14 +142,15 @@ JX.install('Event', {
|
||||||
* @task info
|
* @task info
|
||||||
*/
|
*/
|
||||||
isNormalMouseEvent : function() {
|
isNormalMouseEvent : function() {
|
||||||
var supportedEvents = ['click','mouseup','mousedown'];
|
var supportedEvents = ['click', 'mouseup', 'mousedown'];
|
||||||
|
|
||||||
if (supportedEvents.indexOf(this.getType()) == -1) {
|
if (supportedEvents.indexOf(this.getType()) == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var r = this.getRawEvent();
|
var r = this.getRawEvent();
|
||||||
if (r.metaKey || r.altKey || r.ctrlkey || r.shiftKey) {
|
|
||||||
|
if (r.metaKey || r.altKey || r.ctrlKey || r.shiftKey) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1873,16 +1873,17 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'javelin-behavior-pholio-mock-view' =>
|
'javelin-behavior-pholio-mock-view' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/e2778b8e/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
|
'uri' => '/res/b7c2b169/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-behavior',
|
0 => 'javelin-behavior',
|
||||||
1 => 'javelin-stratcom',
|
1 => 'javelin-util',
|
||||||
2 => 'javelin-dom',
|
2 => 'javelin-stratcom',
|
||||||
3 => 'javelin-vector',
|
3 => 'javelin-dom',
|
||||||
4 => 'javelin-magical-init',
|
4 => 'javelin-vector',
|
||||||
5 => 'javelin-request',
|
5 => 'javelin-magical-init',
|
||||||
|
6 => 'javelin-request',
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
|
'disk' => '/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
|
||||||
),
|
),
|
||||||
|
@ -3217,7 +3218,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'pholio-css' =>
|
'pholio-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/ecd07cd8/rsrc/css/application/pholio/pholio.css',
|
'uri' => '/res/4ca7889f/rsrc/css/application/pholio/pholio.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -16,10 +16,12 @@ final class PholioMockImagesView extends AphrontView {
|
||||||
|
|
||||||
$mock = $this->mock;
|
$mock = $this->mock;
|
||||||
|
|
||||||
$main_image_id = celerity_generate_unique_node_id();
|
|
||||||
require_celerity_resource('javelin-behavior-pholio-mock-view');
|
require_celerity_resource('javelin-behavior-pholio-mock-view');
|
||||||
|
|
||||||
$images = array();
|
$images = array();
|
||||||
|
$panel_id = celerity_generate_unique_node_id();
|
||||||
|
$viewport_id = celerity_generate_unique_node_id();
|
||||||
|
|
||||||
foreach ($mock->getImages() as $image) {
|
foreach ($mock->getImages() as $image) {
|
||||||
$images[] = array(
|
$images[] = array(
|
||||||
'id' => $image->getID(),
|
'id' => $image->getID(),
|
||||||
|
@ -28,8 +30,9 @@ final class PholioMockImagesView extends AphrontView {
|
||||||
}
|
}
|
||||||
|
|
||||||
$config = array(
|
$config = array(
|
||||||
'mainID' => $main_image_id,
|
|
||||||
'mockID' => $mock->getID(),
|
'mockID' => $mock->getID(),
|
||||||
|
'panelID' => $panel_id,
|
||||||
|
'viewportID' => $viewport_id,
|
||||||
'images' => $images,
|
'images' => $images,
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -37,25 +40,22 @@ final class PholioMockImagesView extends AphrontView {
|
||||||
|
|
||||||
$mockview = '';
|
$mockview = '';
|
||||||
|
|
||||||
$main_image = head($mock->getImages());
|
$mock_wrapper = phutil_tag(
|
||||||
|
|
||||||
$main_image_tag = javelin_tag(
|
|
||||||
'img',
|
|
||||||
array(
|
|
||||||
'id' => $main_image_id,
|
|
||||||
'sigil' => 'mock-image',
|
|
||||||
'class' => 'pholio-mock-image',
|
|
||||||
'style' => 'display: none;',
|
|
||||||
));
|
|
||||||
|
|
||||||
$main_image_tag = javelin_tag(
|
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
'id' => 'mock-wrapper',
|
'id' => $viewport_id,
|
||||||
'sigil' => 'mock-wrapper',
|
'class' => 'pholio-mock-image-viewport'
|
||||||
'class' => 'pholio-mock-wrapper'
|
|
||||||
),
|
),
|
||||||
$main_image_tag);
|
'');
|
||||||
|
|
||||||
|
$mock_wrapper = javelin_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'id' => $panel_id,
|
||||||
|
'sigil' => 'mock-panel',
|
||||||
|
'class' => 'pholio-mock-image-panel',
|
||||||
|
),
|
||||||
|
$mock_wrapper);
|
||||||
|
|
||||||
$inline_comments_holder = javelin_tag(
|
$inline_comments_holder = javelin_tag(
|
||||||
'div',
|
'div',
|
||||||
|
@ -72,7 +72,7 @@ final class PholioMockImagesView extends AphrontView {
|
||||||
'class' => 'pholio-mock-image-container',
|
'class' => 'pholio-mock-image-container',
|
||||||
'id' => 'pholio-mock-image-container'
|
'id' => 'pholio-mock-image-container'
|
||||||
),
|
),
|
||||||
array($main_image_tag, $inline_comments_holder));
|
array($mock_wrapper, $inline_comments_holder));
|
||||||
|
|
||||||
if (count($mock->getImages()) > 1) {
|
if (count($mock->getImages()) > 1) {
|
||||||
$thumbnails = array();
|
$thumbnails = array();
|
||||||
|
|
|
@ -38,7 +38,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.pholio-mock-image {
|
.pholio-mock-image {
|
||||||
display: inline-block;
|
margin: auto;
|
||||||
|
cursor: crosshair;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pholio-mock-select-border {
|
.pholio-mock-select-border {
|
||||||
|
@ -55,12 +56,15 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pholio-mock-wrapper {
|
.pholio-mock-image-panel {
|
||||||
|
padding: 20px;
|
||||||
|
margin-right: 320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pholio-mock-image-viewport {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 20px 340px 20px 20px;
|
margin: auto;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: crosshair;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pholio-mock-inline-comments {
|
.pholio-mock-inline-comments {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* @provides javelin-behavior-pholio-mock-view
|
* @provides javelin-behavior-pholio-mock-view
|
||||||
* @requires javelin-behavior
|
* @requires javelin-behavior
|
||||||
|
* javelin-util
|
||||||
* javelin-stratcom
|
* javelin-stratcom
|
||||||
* javelin-dom
|
* javelin-dom
|
||||||
* javelin-vector
|
* javelin-vector
|
||||||
|
@ -10,9 +11,10 @@
|
||||||
JX.behavior('pholio-mock-view', function(config) {
|
JX.behavior('pholio-mock-view', function(config) {
|
||||||
var is_dragging = false;
|
var is_dragging = false;
|
||||||
|
|
||||||
var wrapper = JX.$('mock-wrapper');
|
|
||||||
var drag_begin;
|
var drag_begin;
|
||||||
var drag_end;
|
var drag_end;
|
||||||
|
var panel = JX.$(config.panelID);
|
||||||
|
var viewport = JX.$(config.viewportID);
|
||||||
|
|
||||||
var selection_border;
|
var selection_border;
|
||||||
var selection_fill;
|
var selection_fill;
|
||||||
|
@ -29,16 +31,38 @@ JX.behavior('pholio-mock-view', function(config) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onload_image(id) {
|
||||||
|
if (active_image.id != id) {
|
||||||
|
// The user has clicked another image before this one loaded, so just
|
||||||
|
// bail.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the image is too wide for the viewport, scale it down so it fits.
|
||||||
|
// (If it is too tall, we just let the user scroll.)
|
||||||
|
var w = JX.Vector.getDim(panel);
|
||||||
|
w.x -= 40;
|
||||||
|
if (w.x < this.naturalWidth) {
|
||||||
|
var scale = w.x / this.naturalWidth;
|
||||||
|
this.width = Math.floor(scale * this.naturalWidth);
|
||||||
|
this.height = Math.floor(scale * this.naturalHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
active_image.tag = this;
|
||||||
|
|
||||||
|
// NOTE: This also clears inline comment reticles.
|
||||||
|
JX.DOM.setContent(viewport, this);
|
||||||
|
|
||||||
|
redraw_inlines(active_image.id);
|
||||||
|
}
|
||||||
|
|
||||||
function select_image(image_id) {
|
function select_image(image_id) {
|
||||||
var image = get_image(image_id);
|
active_image = get_image(image_id);
|
||||||
active_image = image;
|
active_image.tag = null;
|
||||||
|
|
||||||
var main = JX.$(config.mainID);
|
var img = JX.$N('img', {className: 'pholio-mock-image'});
|
||||||
main.src = image.fullURI;
|
img.onload = JX.bind(img, onload_image, active_image.id);
|
||||||
JX.DOM.show(main);
|
img.src = active_image.fullURI;
|
||||||
|
|
||||||
// NOTE: This is to clear inline comment reticles.
|
|
||||||
JX.DOM.setContent(wrapper, main);
|
|
||||||
|
|
||||||
load_inline_comments();
|
load_inline_comments();
|
||||||
}
|
}
|
||||||
|
@ -54,7 +78,7 @@ JX.behavior('pholio-mock-view', function(config) {
|
||||||
// Select and show the first image.
|
// Select and show the first image.
|
||||||
select_image(config.images[0].id);
|
select_image(config.images[0].id);
|
||||||
|
|
||||||
JX.Stratcom.listen('mousedown', 'mock-wrapper', function(e) {
|
JX.Stratcom.listen('mousedown', 'mock-panel', function(e) {
|
||||||
if (!e.isNormalMouseEvent()) {
|
if (!e.isNormalMouseEvent()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -111,8 +135,8 @@ JX.behavior('pholio-mock-view', function(config) {
|
||||||
|
|
||||||
var dialog = JX.$('pholio-new-inline-comment-dialog');
|
var dialog = JX.$('pholio-new-inline-comment-dialog');
|
||||||
|
|
||||||
var wrapperVector = JX.$V(wrapper);
|
var viewportVector = JX.$V(viewport);
|
||||||
var wrapperDimensions = JX.Vector.getDim(wrapper);
|
var viewportDimensions = JX.Vector.getDim(viewport);
|
||||||
|
|
||||||
JX.$V(
|
JX.$V(
|
||||||
// TODO: This is a little funky for now.
|
// TODO: This is a little funky for now.
|
||||||
|
@ -145,6 +169,13 @@ JX.behavior('pholio-mock-view', function(config) {
|
||||||
|
|
||||||
for (var ii = 0; ii < inlines.length; ii++) {
|
for (var ii = 0; ii < inlines.length; ii++) {
|
||||||
var inline = inlines[ii];
|
var inline = inlines[ii];
|
||||||
|
JX.DOM.appendContent(comment_holder, JX.$H(inline.contentHTML));
|
||||||
|
|
||||||
|
if (!active_image.tag) {
|
||||||
|
// The image itself hasn't loaded yet, so we can't draw the inline
|
||||||
|
// reticles.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var inlineSelection = JX.$N(
|
var inlineSelection = JX.$N(
|
||||||
'div',
|
'div',
|
||||||
|
@ -158,9 +189,8 @@ JX.behavior('pholio-mock-view', function(config) {
|
||||||
{phid: inline.phid});
|
{phid: inline.phid});
|
||||||
|
|
||||||
JX.Stratcom.addSigil(inlineSelection, "image_selection");
|
JX.Stratcom.addSigil(inlineSelection, "image_selection");
|
||||||
JX.DOM.appendContent(comment_holder, JX.$H(inline.contentHTML));
|
|
||||||
|
|
||||||
JX.DOM.appendContent(wrapper, inlineSelection);
|
JX.DOM.appendContent(viewport, inlineSelection);
|
||||||
|
|
||||||
position_inline_rectangle(inline, inlineSelection);
|
position_inline_rectangle(inline, inlineSelection);
|
||||||
|
|
||||||
|
@ -180,22 +210,26 @@ JX.behavior('pholio-mock-view', function(config) {
|
||||||
{phid: inline.phid});
|
{phid: inline.phid});
|
||||||
|
|
||||||
JX.Stratcom.addSigil(inlineDraft, "image_selection");
|
JX.Stratcom.addSigil(inlineDraft, "image_selection");
|
||||||
JX.DOM.appendContent(wrapper, inlineDraft);
|
JX.DOM.appendContent(viewport, inlineDraft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function position_inline_rectangle(inline, rect) {
|
function position_inline_rectangle(inline, rect) {
|
||||||
JX.$V(inline.x, inline.y).setPos(rect);
|
var scale = active_image.tag.width / active_image.tag.naturalWidth;
|
||||||
JX.$V(inline.width, inline.height).setDim(rect);
|
|
||||||
|
JX.$V(scale * inline.x, scale * inline.y).setPos(rect);
|
||||||
|
JX.$V(scale * inline.width, scale * inline.height).setDim(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_image_xy(p) {
|
function get_image_xy(p) {
|
||||||
var main = JX.$(config.mainID);
|
var img = active_image.tag;
|
||||||
var mainp = JX.$V(main);
|
var imgp = JX.$V(img);
|
||||||
|
|
||||||
var x = Math.max(0, Math.min(p.x - mainp.x, main.naturalWidth));
|
var scale = 1 / get_image_scale();
|
||||||
var y = Math.max(0, Math.min(p.y - mainp.y, main.naturalHeight));
|
|
||||||
|
var x = scale * Math.max(0, Math.min(p.x - imgp.x, img.width));
|
||||||
|
var y = scale * Math.max(0, Math.min(p.y - imgp.y, img.height));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: x,
|
x: x,
|
||||||
|
@ -203,6 +237,11 @@ JX.behavior('pholio-mock-view', function(config) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_image_scale() {
|
||||||
|
var img = active_image.tag;
|
||||||
|
return img.width / img.naturalWidth;
|
||||||
|
}
|
||||||
|
|
||||||
function redraw_selection() {
|
function redraw_selection() {
|
||||||
selection_border = selection_border || JX.$N(
|
selection_border = selection_border || JX.$N(
|
||||||
'div',
|
'div',
|
||||||
|
@ -220,10 +259,17 @@ JX.behavior('pholio-mock-view', function(config) {
|
||||||
Math.max(drag_begin.x, drag_end.x) - p.x,
|
Math.max(drag_begin.x, drag_end.x) - p.x,
|
||||||
Math.max(drag_begin.y, drag_end.y) - p.y);
|
Math.max(drag_begin.y, drag_end.y) - p.y);
|
||||||
|
|
||||||
|
var scale = get_image_scale();
|
||||||
|
|
||||||
|
p.x *= scale;
|
||||||
|
p.y *= scale;
|
||||||
|
d.x *= scale;
|
||||||
|
d.y *= scale;
|
||||||
|
|
||||||
var nodes = [selection_border, selection_fill];
|
var nodes = [selection_border, selection_fill];
|
||||||
for (var ii = 0; ii < nodes.length; ii++) {
|
for (var ii = 0; ii < nodes.length; ii++) {
|
||||||
var node = nodes[ii];
|
var node = nodes[ii];
|
||||||
wrapper.appendChild(node);
|
viewport.appendChild(node);
|
||||||
p.setPos(node);
|
p.setPos(node);
|
||||||
d.setDim(node);
|
d.setDim(node);
|
||||||
}
|
}
|
||||||
|
@ -393,4 +439,5 @@ JX.behavior('pholio-mock-view', function(config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
load_inline_comments();
|
load_inline_comments();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue