1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 08:42:41 +01:00

PHUIImageMask

Summary: Adds a PHUI class for display images on a center point, with or without a mask.

Test Plan:
I am bad a math, so like, check that for me please. I tested using Photoshop. Class may need tweaked depending how we store the inline-comment coords.

{F167829}

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: epriestley, Korvin

Differential Revision: https://secure.phabricator.com/D9614
This commit is contained in:
Chad Little 2014-06-18 14:09:37 -07:00
parent 47964077ef
commit ca801c7ad4
10 changed files with 283 additions and 12 deletions

View file

@ -81,7 +81,7 @@ return array(
'rsrc/css/application/phame/phame.css' => '19ecc703', 'rsrc/css/application/phame/phame.css' => '19ecc703',
'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', 'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee',
'rsrc/css/application/pholio/pholio-inline-comments.css' => '95004a57', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '95004a57',
'rsrc/css/application/pholio/pholio.css' => '6f87390f', 'rsrc/css/application/pholio/pholio.css' => 'd0502625',
'rsrc/css/application/phortune/phortune-credit-card-form.css' => 'b25b4beb', 'rsrc/css/application/phortune/phortune-credit-card-form.css' => 'b25b4beb',
'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad', 'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad',
'rsrc/css/application/phriction/phriction-document-css.css' => '7d7f0071', 'rsrc/css/application/phriction/phriction-document-css.css' => '7d7f0071',
@ -131,6 +131,7 @@ return array(
'rsrc/css/phui/phui-form.css' => 'b78ec020', 'rsrc/css/phui/phui-form.css' => 'b78ec020',
'rsrc/css/phui/phui-header-view.css' => 'a2071a67', 'rsrc/css/phui/phui-header-view.css' => 'a2071a67',
'rsrc/css/phui/phui-icon.css' => 'd8526aa1', 'rsrc/css/phui/phui-icon.css' => 'd8526aa1',
'rsrc/css/phui/phui-image-mask.css' => '5f4a6d5d',
'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1',
'rsrc/css/phui/phui-list.css' => '43ed2d93', 'rsrc/css/phui/phui-list.css' => '43ed2d93',
'rsrc/css/phui/phui-object-box.css' => 'ce92d8ec', 'rsrc/css/phui/phui-object-box.css' => 'ce92d8ec',
@ -230,6 +231,7 @@ return array(
'rsrc/image/credit_cards.png' => '72b8ede8', 'rsrc/image/credit_cards.png' => '72b8ede8',
'rsrc/image/darkload.gif' => '1ffd3ec6', 'rsrc/image/darkload.gif' => '1ffd3ec6',
'rsrc/image/divot.png' => '94dded62', 'rsrc/image/divot.png' => '94dded62',
'rsrc/image/examples/hero.png' => '979a86ae',
'rsrc/image/grippy_texture.png' => 'aca81e2f', 'rsrc/image/grippy_texture.png' => 'aca81e2f',
'rsrc/image/icon/fatcow/arrow_branch.png' => '2537c01c', 'rsrc/image/icon/fatcow/arrow_branch.png' => '2537c01c',
'rsrc/image/icon/fatcow/arrow_merge.png' => '21b660e0', 'rsrc/image/icon/fatcow/arrow_merge.png' => '21b660e0',
@ -750,7 +752,7 @@ return array(
'phabricator-uiexample-reactor-sendproperties' => '551add57', 'phabricator-uiexample-reactor-sendproperties' => '551add57',
'phabricator-zindex-css' => 'efb673ac', 'phabricator-zindex-css' => 'efb673ac',
'phame-css' => '19ecc703', 'phame-css' => '19ecc703',
'pholio-css' => '6f87390f', 'pholio-css' => 'd0502625',
'pholio-edit-css' => '3ad9d1ee', 'pholio-edit-css' => '3ad9d1ee',
'pholio-inline-comments-css' => '95004a57', 'pholio-inline-comments-css' => '95004a57',
'phortune-credit-card-form' => '2290aeef', 'phortune-credit-card-form' => '2290aeef',
@ -771,6 +773,7 @@ return array(
'phui-form-view-css' => 'ed856191', 'phui-form-view-css' => 'ed856191',
'phui-header-view-css' => 'a2071a67', 'phui-header-view-css' => 'a2071a67',
'phui-icon-view-css' => 'd8526aa1', 'phui-icon-view-css' => 'd8526aa1',
'phui-image-mask-css' => '5f4a6d5d',
'phui-info-panel-css' => '27ea50a1', 'phui-info-panel-css' => '27ea50a1',
'phui-list-view-css' => '43ed2d93', 'phui-list-view-css' => '43ed2d93',
'phui-object-box-css' => 'ce92d8ec', 'phui-object-box-css' => 'ce92d8ec',

View file

@ -1026,6 +1026,8 @@ phutil_register_library_map(array(
'PHUIHeaderView' => 'view/phui/PHUIHeaderView.php', 'PHUIHeaderView' => 'view/phui/PHUIHeaderView.php',
'PHUIIconExample' => 'applications/uiexample/examples/PHUIIconExample.php', 'PHUIIconExample' => 'applications/uiexample/examples/PHUIIconExample.php',
'PHUIIconView' => 'view/phui/PHUIIconView.php', 'PHUIIconView' => 'view/phui/PHUIIconView.php',
'PHUIImageMaskExample' => 'applications/uiexample/examples/PHUIImageMaskExample.php',
'PHUIImageMaskView' => 'view/phui/PHUIImageMaskView.php',
'PHUIInfoPanelExample' => 'applications/uiexample/examples/PHUIInfoPanelExample.php', 'PHUIInfoPanelExample' => 'applications/uiexample/examples/PHUIInfoPanelExample.php',
'PHUIInfoPanelView' => 'view/phui/PHUIInfoPanelView.php', 'PHUIInfoPanelView' => 'view/phui/PHUIInfoPanelView.php',
'PHUIListExample' => 'applications/uiexample/examples/PHUIListExample.php', 'PHUIListExample' => 'applications/uiexample/examples/PHUIListExample.php',
@ -3793,6 +3795,8 @@ phutil_register_library_map(array(
'PHUIHeaderView' => 'AphrontView', 'PHUIHeaderView' => 'AphrontView',
'PHUIIconExample' => 'PhabricatorUIExample', 'PHUIIconExample' => 'PhabricatorUIExample',
'PHUIIconView' => 'AphrontTagView', 'PHUIIconView' => 'AphrontTagView',
'PHUIImageMaskExample' => 'PhabricatorUIExample',
'PHUIImageMaskView' => 'AphrontTagView',
'PHUIInfoPanelExample' => 'PhabricatorUIExample', 'PHUIInfoPanelExample' => 'PhabricatorUIExample',
'PHUIInfoPanelView' => 'AphrontView', 'PHUIInfoPanelView' => 'AphrontView',
'PHUIListExample' => 'PhabricatorUIExample', 'PHUIListExample' => 'PhabricatorUIExample',

View file

@ -100,6 +100,7 @@ final class PholioMockViewController extends PholioController {
$xaction_view = id(new PholioTransactionView()) $xaction_view = id(new PholioTransactionView())
->setUser($this->getRequest()->getUser()) ->setUser($this->getRequest()->getUser())
->setMock($mock)
->setObjectPHID($mock->getPHID()) ->setObjectPHID($mock->getPHID())
->setTransactions($xactions) ->setTransactions($xactions)
->setMarkupEngine($engine); ->setMarkupEngine($engine);

View file

@ -6,6 +6,17 @@
final class PholioTransactionView final class PholioTransactionView
extends PhabricatorApplicationTransactionView { extends PhabricatorApplicationTransactionView {
private $mock;
public function setMock($mock) {
$this->mock = $mock;
return $this;
}
public function getMock() {
return $this->mock;
}
protected function shouldGroupTransactions( protected function shouldGroupTransactions(
PhabricatorApplicationTransaction $u, PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) { PhabricatorApplicationTransaction $v) {
@ -87,12 +98,31 @@ final class PholioTransactionView
private function renderInlineContent(PholioTransaction $inline) { private function renderInlineContent(PholioTransaction $inline) {
$comment = $inline->getComment(); $comment = $inline->getComment();
$mock = $this->getMock();
$images = $mock->getAllImages();
$images = mpull($images, null, 'getID');
$thumb = phutil_tag( $image = idx($images, $comment->getImageID());
'img', if (!$image) {
array( throw new Exception('No image attached!');
'src' => '/pholio/inline/thumb/'.$comment->getImageID(), }
));
$file = $image->getFile();
if (!$file->isViewableImage()) {
throw new Exception('File is not viewable.');
}
$image_uri = $file->getBestURI();
$thumb = id(new PHUIImageMaskView())
->addClass('mrl')
->setImage($image_uri)
->setDisplayHeight(100)
->setDisplayWidth(200)
->withMask(true)
->centerViewOnPoint(
$comment->getX(), $comment->getY(),
$comment->getHeight(), $comment->getWidth());
$link = phutil_tag( $link = phutil_tag(
'a', 'a',

View file

@ -114,5 +114,5 @@ final class PHUIBoxExample extends PhabricatorUIExample {
$head4, $head4,
$obj4, $obj4,
)); ));
} }
} }

View file

@ -0,0 +1,88 @@
<?php
final class PHUIImageMaskExample extends PhabricatorUIExample {
public function getName() {
return 'Image Masks';
}
public function getDescription() {
return 'Display images with crops.';
}
public function renderExample() {
$image = celerity_get_resource_uri('/rsrc/image/examples/hero.png');
$display_height = 100;
$display_width = 200;
$mask1 = id(new PHUIImageMaskView())
->addClass('ml')
->setImage($image)
->setDisplayHeight($display_height)
->setDisplayWidth($display_width)
->centerViewOnPoint(265, 185, 30, 140);
$mask2 = id(new PHUIImageMaskView())
->addClass('ml')
->setImage($image)
->setDisplayHeight($display_height)
->setDisplayWidth($display_width)
->centerViewOnPoint(18, 18, 40, 80);
$mask3 = id(new PHUIImageMaskView())
->addClass('ml')
->setImage($image)
->setDisplayHeight($display_height)
->setDisplayWidth($display_width)
->centerViewOnPoint(265, 185, 30, 140)
->withMask(true);
$mask4 = id(new PHUIImageMaskView())
->addClass('ml')
->setImage($image)
->setDisplayHeight($display_height)
->setDisplayWidth($display_width)
->centerViewOnPoint(18, 18, 40, 80)
->withMask(true);
$mask5 = id(new PHUIImageMaskView())
->addClass('ml')
->setImage($image)
->setDisplayHeight($display_height)
->setDisplayWidth($display_width)
->centerViewOnPoint(254, 272, 60, 240)
->withMask(true);
$box1 = id(new PHUIObjectBoxView())
->setHeaderText(pht('Center is in the middle'))
->appendChild($mask1);
$box2 = id(new PHUIObjectBoxView())
->setHeaderText(pht('Center is on an edge'))
->appendChild($mask2);
$box3 = id(new PHUIObjectBoxView())
->setHeaderText(pht('Center Masked'))
->appendChild($mask3);
$box4 = id(new PHUIObjectBoxView())
->setHeaderText(pht('Edge Masked'))
->appendChild($mask4);
$box5 = id(new PHUIObjectBoxView())
->setHeaderText(pht('Wide Masked'))
->appendChild($mask5);
return phutil_tag(
'div',
array(),
array(
$box1,
$box2,
$box3,
$box4,
$box5
));
}
}

View file

@ -0,0 +1,116 @@
<?php
final class PHUIImageMaskView extends AphrontTagView {
private $image;
private $withMask;
private $displayWidth;
private $displayHeight;
private $centerX;
private $centerY;
private $maskH;
private $maskW;
public function setImage($image) {
$this->image = $image;
return $this;
}
public function setDisplayWidth($width) {
$this->displayWidth = $width;
return $this;
}
public function setDisplayHeight($height) {
$this->displayHeight = $height;
return $this;
}
public function centerViewOnPoint($x, $y, $h, $w) {
$this->centerX = $x;
$this->centerY = $y;
$this->maskH = $h;
$this->maskW = $w;
return $this;
}
public function withMask($mask) {
$this->withMask = $mask;
return $this;
}
public function getTagName() {
return 'div';
}
public function getTagAttributes() {
require_celerity_resource('phui-image-mask-css');
$classes = array();
$classes[] = 'phui-image-mask';
$styles = array();
$styles[] = 'height: '.$this->displayHeight.'px;';
$styles[] = 'width: '.$this->displayWidth.'px;';
return array(
'class' => implode(' ', $classes),
'styles' => implode(' ', $styles),
);
}
public function getTagContent() {
/* Center it in the middle of the selected area */
$center_x = round($this->centerX + ($this->maskW / 2));
$center_y = round($this->centerY + ($this->maskH / 2));
$center_x = round($center_x - ($this->displayWidth / 2));
$center_y = round($center_y - ($this->displayHeight / 2));
$center_x = -$center_x;
$center_y = -$center_y;
$classes = array();
$classes[] = 'phui-image-mask-image';
$styles = array();
$styles[] = 'height: '.$this->displayHeight.'px;';
$styles[] = 'width: '.$this->displayWidth.'px;';
$styles[] = 'background-image: url('.$this->image.');';
$styles[] = 'background-position: '.$center_x.'px '.$center_y.'px;';
$mask = null;
if ($this->withMask) {
/* The mask is a 300px border around a transparent box.
so we do the math here to position the box correctly. */
$border = 300;
$left = round((($this->displayWidth - $this->maskW) / 2) - $border);
$top = round((($this->displayHeight - $this->maskH) / 2) - $border);
$mstyles = array();
$mstyles[] = 'left: '.$left.'px;';
$mstyles[] = 'top: '.$top.'px;';
$mstyles[] = 'height: '.$this->maskH.'px;';
$mstyles[] = 'width: '.$this->maskW.'px;';
$mask = phutil_tag(
'span',
array(
'class' => 'phui-image-mask-mask',
'style' => implode(' ', $mstyles),
),
null);
}
return phutil_tag(
'div',
array(
'class' => implode(' ', $classes),
'style' => implode(' ', $styles),
),
$mask);
}
}

View file

@ -99,19 +99,21 @@
.pholio-transaction-inline-comment .transaction-comment { .pholio-transaction-inline-comment .transaction-comment {
display: table-cell; display: table-cell;
vertical-align: middle; vertical-align: top;
padding-left: 8px; padding-left: 8px;
padding-top: 4px;
} }
.pholio-mock-reticle { .pholio-mock-reticle {
position: absolute; position: absolute;
display: none; display: none;
box-sizing: border-box; box-sizing: border-box;
border: 4px solid transparent;
} }
.pholio-mock-reticle-selection { .pholio-mock-reticle-selection {
background-color: rgba(255, 255, 255, 0.50); border: 1px solid rgba(0,0,0,.5);
border: 1px dashed #000; box-shadow: 0 0 0 4px rgba(255,255,255,.5);
} }
.pholio-mock-reticle-draft { .pholio-mock-reticle-draft {
@ -130,8 +132,12 @@
.pholio-mock-reticle-draft:hover, .pholio-mock-reticle-draft:hover,
.pholio-mock-reticle-final:hover { .pholio-mock-reticle-final:hover {
background-color: rgba(255, 255, 255, 0.50); border: 1px solid rgba(0,0,0,.5);
box-shadow: 0 0 0 4px rgba(255,255,255,.5);
cursor: pointer; cursor: pointer;
color: transparent;
text-shadow: none;
-webkit-text-stroke: 0;
} }
.device-desktop .mock-has-cursor .pholio-mock-reticle { .device-desktop .mock-has-cursor .pholio-mock-reticle {

View file

@ -0,0 +1,23 @@
/**
* @provides phui-image-mask-css
*/
.phui-image-mask {
background: url('/rsrc/image/checker_lighter.png');
display: inline-block;
border: 1px solid {$lightblueborder};
padding: 4px;
position: relative;
overflow: hidden;
}
.phui-image-mask-image {
background-repeat: no-repeat;
}
.phui-image-mask-mask {
border: 300px solid rgba(0, 0, 0, 0.5);
background-clip: content-box;
position: absolute;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB