ImageGrid/ui/layout.less
Alex A. Naanou c3cb62f9be added node-webkit support, not yet final...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2013-06-08 05:46:57 +04:00

919 lines
19 KiB
Plaintext
Executable File

/**********************************************************************
*
**********************************************************************/
/******************************************************** Settings ***/
@ribbon-mark-offset: 5px;
@ribbon-mark-size: 10px;
@single-image-indicator-size: 10px;
/********************************************************** Mixins ***/
.user-select (@mode: auto) {
-moz-user-select: @mode;
-webkit-user-select: @mode;
-o-user-select: @mode;
-ms-user-select: @mode;
user-select: @mode;
}
.origin (@x:top, @y:left) {
-webkit-transform-origin: @arguments;
-ms-transform-origin: @arguments;
transform-origin: @arguments;
}
.transform (@deg:0deg, @scaleX:1, @scaleY:1) {
-webkit-transform: rotate(@deg) scaleY(@scaleY) scaleX(@scaleX);
-moz-transform: rotate(@deg) scaleY(@scaleY) scaleX(@scaleX);
-o-transform: rotate(@deg) scaleY(@scaleY) scaleX(@scaleX);
-ms-transform: rotate(@deg) scaleY(@scaleY) scaleX(@scaleX);
transform: rotate(@deg) scaleY(@scaleY) scaleX(@scaleX);
}
.rotate (@deg) {
.transform(@deg)
}
.flipped-vertically () {
.transform(0deg, 1, -1)
}
.flipped-horizontally () {
.transform(0deg, -1, 1)
}
/********************************************************* utility ***/
.expanding-text .hidden {
display: none;
}
.expanding-text:hover .shown {
display: none;
}
.expanding-text:hover .hidden {
display: inline;
}
/*********************************************************************/
body {
font-family: sans-serif;
padding: 0px;
margin: 0px;
}
/************************************************************** UI ***/
.title-bar {
display: block;
position: fixed;
content: "";
top: 0px;
left: 0px;
height: 20px;
width: 100%;
color: white;
background: black;
overflow: hidden;
opacity: 0;
z-index: 10000;
/* node-webkit */
-webkit-app-region: drag;
}
.title-bar:hover {
opacity: 1;
}
.title-bar .title {
display: inline-block;
float: left;
height: 20px;
width: auto;
color: white;
background: transparent;
font-size: 11px;
font-style: italic;
font-weight: bold;
vertical-align: middle;
text-align: left;
margin: 2px;
margin-left: 10px;
}
.title-bar .button {
display: inline-block;
float: right;
width: 20px;
height: 20px;
color: white;
background: transparent;
font-size: 18px;
vertical-align: middle;
/* node-webkit */
-webkit-app-region: no-drag;
}
.title-bar .button:hover {
cursor: hand;
}
.title-bar .close:hover {
color: red;
}
/*
.full-screen-mode .title-bar {
display: none;
}
*/
/********************************************************** Viewer ***/
.viewer {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
/*border: solid blue 1px;*/
box-sizing: border-box;
.user-select(none);
}
/****************************************************** Ribbon set ***/
.ribbon-set {
position: absolute;
display: block;
/* NOTE: this needs for scaling/zooming to behave correctly and not
shift the element, when its dimensions change...
...this is because .ribbon-set will both be used for scaling
and aligning... */
.origin(top, left);
}
.ribbon-set:empty:after {
display: block;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
content: "Empty";
text-align: center;
}
/********************************************************** Ribbon ***/
.ribbon {
position: relative;
display: block;
height: auto;
min-width: 0px;
overflow: visible;
white-space: nowrap;
font-size: 0;
margin-top: 20px;
margin-bottom: 20px;
}
.ribbon:empty {
display: none;
}
.ribbon:first-child {
margin-top: 0px;
}
.ribbon:last-child {
margin-bottom: 0px;
}
/*********************************************************** Image ***/
.image {
position: relative;
display: inline-block;
vertical-align: middle;
text-align:left;
width: 300px;
height: 300px;
font-size: 12pt;
overflow: hidden;
box-sizing: border-box;
color: white;
text-shadow: black 0.1em 0.1em 0.4em, black 0.1em 0.1em;
background: no-repeat 50% black;
background-size: contain;
/* XXX do we need this? */
border: solid black 5px;
}
.current.image {
background: no-repeat 50% black;
background-size: contain;
/* XXX remove this... */
border: solid red 5px;
}
/* image turning... */
/* NOTE: need to account for proportions after turning... */
.image[orientation="90"] {
.rotate(90deg);
}
.image[orientation="180"] {
.rotate(180deg);
}
.image[orientation="270"] {
.rotate(270deg);
}
/* Flipped vertically only... */
/* NOTE: wee need to do all possible combinations here as we can't
combine different parts of a transform attr from different
classes */
.image[flipped*="vertical"] {
.flipped-vertically;
}
.image[orientation="90"][flipped="vertical"] {
.transform(90deg, 1, -1)
}
.image[orientation="180"][flipped="vertical"] {
.transform(180deg, 1, -1)
}
.image[orientation="270"][flipped="vertical"] {
.transform(270deg, 1, -1)
}
/* Flipped horizontally only... */
.image[flipped*="horizontal"] {
.flipped-horizontally;
}
.image[orientation="90"][flipped="horizontal"] {
.transform(90deg, -1)
}
.image[orientation="180"][flipped="horizontal"] {
.transform(180deg, -1)
}
.image[orientation="270"][flipped="horizontal"] {
.transform(270deg, -1)
}
/* Flipped vertically and horizontally... */
.image[flipped*="vertical"][flipped*="horizontal"] {
.transform(0deg, -1, -1)
}
.image[orientation="90"][flipped*="vertical"][flipped*="horizontal"] {
.transform(90deg, -1, -1)
}
.image[orientation="180"][flipped*="vertical"][flipped*="horizontal"] {
.transform(180deg, -1, -1)
}
.image[orientation="270"][flipped*="vertical"][flipped*="horizontal"] {
.transform(270deg, -1, -1)
}
/* default backgrounds */
/* XXX not sure if we need these...
.image {
background-image: url(images/loading.gif);
}
.image[orientation="90"] {
background-image: url(images/loading-90deg.gif);
}
.image[orientation="180"] {
background-image: url(images/loading-180deg.gif);
}
.image[orientation="270"] {
background-image: url(images/loading-270deg.gif);
}
*/
/***************************************************** Image marks ***/
.marks-visible.viewer .marked.image:after {
display: block;
position: absolute;
content: "";
font-size: 0pt;
border: none;
width: @ribbon-mark-size;
height: @ribbon-mark-size;
top: auto;
bottom: @ribbon-mark-offset;
left: auto;
right: @ribbon-mark-offset;
border-radius: 50%;
background: blue;
}
.marks-visible.viewer .marked.image[orientation="270"][flipped*="vertical"][flipped*="horizontal"]:after,
.marks-visible.viewer .marked.image:not([orientation])[flipped*="vertical"]:after,
.marks-visible.viewer .marked.image[orientation="0"][flipped*="vertical"]:after,
.marks-visible.viewer .marked.image[orientation="180"][flipped="horizontal"]:after,
.marks-visible.viewer .marked.image[orientation="90"]:not([flipped]):after {
top: @ribbon-mark-offset;
bottom: auto:
left: auto;
right: @ribbon-mark-offset;
}
.marks-visible.viewer .marked.image:not([orientation])[flipped*="vertical"][flipped*="horizontal"]:after,
.marks-visible.viewer .marked.image[orientation="0"][flipped*="vertical"][flipped*="horizontal"]:after,
.marks-visible.viewer .marked.image[orientation="270"][flipped="vertical"]:after,
.marks-visible.viewer .marked.image[orientation="90"][flipped="horizontal"]:after,
.marks-visible.viewer .marked.image[orientation="180"]:not([flipped]):after {
top: @ribbon-mark-offset;
bottom: auto;
left: @ribbon-mark-offset;
right: auto;
}
.marks-visible.viewer .marked.image[orientation="90"][flipped*="vertical"][flipped*="horizontal"]:after,
.marks-visible.viewer .marked.image[orientation="180"][flipped="vertical"]:after,
.marks-visible.viewer .marked.image:not([orientation])[flipped*="horizontal"]:after,
.marks-visible.viewer .marked.image[orientation="0"][flipped*="horizontal"]:after,
.marks-visible.viewer .marked.image[orientation="270"]:not([flipped]):after {
top: auto;
bottom: @ribbon-mark-offset;
left: @ribbon-mark-offset;
right: auto;
}
/* NOTE: we use a different mark representation for single image mode... */
.marks-visible.single-image-mode.viewer .marked.image:after {
display: none;
}
/* corner mark... (a-la bookmarks in PortableMag)
* XXX account for flipping... */
/*
@ribbon-mark-offset: -15px;
.marks-visible.viewer .marked.image:after {
display: block;
position: absolute;
content: "";
font-size: 0pt;
border: none;
width: 30px;
height: 30px;
top: @ribbon-mark-offset;
right: @ribbon-mark-offset;
background: blue;
.rotate(45deg)
}
.marks-visible.viewer .marked.image[orientation="90"]:after {
top: @ribbon-mark-offset;
left: @ribbon-mark-offset;
}
.marks-visible.viewer .marked.image[orientation="180"]:after {
bottom: @ribbon-mark-offset;
left: @ribbon-mark-offset;
}
.marks-visible.viewer .marked.image[orientation="270"]:after {
bottom: @ribbon-mark-offset;
right: @ribbon-mark-offset;
}
*/
/* XXX should we use opacity??? */
.marked-only-view.viewer:not(.marks-visible) .image:not(.marked) {
opacity: 0.3;
}
/****************************************************** Image info ***/
.image .inline-image-info {
display: none;
position: absolute;
bottom: 0px;
width: 100%;
background: black;
opacity: 0.7;
}
.image .inline-image-info:hover {
.user-select(auto);
}
.image .inline-image-info::selection {
color: white;
background: red;
}
.image-info-visible.viewer .global-image-info,
.image-info-visible.viewer .image:hover .inline-image-info {
display: block;
}
.single-image-mode.viewer .image:hover .inline-image-info {
display: none;
}
.image[orientation="90"] .inline-image-info {
top: auto;
left: 100%;
.origin(bottom, left);
.rotate(-90deg);
}
.image[orientation="180"] .inline-image-info {
top: 0px;
bottom: auto;
.rotate(180deg);
}
.image[orientation="270"] .inline-image-info {
top: auto;
left: auto;
right: 100%;
.origin(bottom, right);
.rotate(90deg);
}
/* compensate for flipping... */
/* XXX START: I hate this code, will think if a better way to do this... */
.image:not([orientation="90"])[flipped*="horizontal"] .inline-image-info {
.flipped-horizontally;
}
.image[orientation="90"][flipped*="horizontal"] .inline-image-info {
top: auto;
bottom: 100%;
left: -100%;
right: auto;
.origin(bottom, right);
.transform(90deg, -1, 1);
}
.image[orientation="180"][flipped*="horizontal"] .inline-image-info {
top: auto;
bottom: 100%;
left: 0px;
right: auto;
.origin(bottom, right);
.transform(180deg, -1, 1);
}
.image[orientation="270"][flipped*="horizontal"] .inline-image-info {
top: auto;
bottom: 0px;
left: 0px;
right: auto;
.origin(bottom, right);
.transform(270deg, -1, 1);
}
.image[flipped*="vertical"] .inline-image-info {
top: 0px;
bottom: auto;
.flipped-vertically;
}
.image[orientation="90"][flipped*="vertical"] .inline-image-info {
top: auto;
bottom: 100%;
left: 100%;
right: auto;
.origin(bottom, left);
.transform(-270deg, 1, -1);
}
.image[orientation="180"][flipped*="vertical"] .inline-image-info {
top: auto;
bottom: 0px;
left: -100%;
right: auto;
.origin(bottom, right);
.transform(180deg, 1, -1);
}
.image[orientation="270"][flipped*="vertical"] .inline-image-info {
top: auto;
bottom: 100%;
left: -100%;
right: auto;
.origin(bottom, right);
.transform(270deg, 1, -1);
}
.image[flipped*="vertical"][flipped*="horizontal"] .inline-image-info {
top: 0px;
bottom: auto;
.transform(0deg, -1, -1);
}
.image[orientation="90"][flipped*="vertical"][flipped*="horizontal"] .inline-image-info {
top: auto;
bottom: 0px;
left: -100%;
right: auto;
.origin(bottom, right);
.transform(-90deg, -1, -1);
}
.image[orientation="180"][flipped*="vertical"][flipped*="horizontal"] .inline-image-info {
top: auto;
bottom: 0px;
left: auto;
right: auto;
.origin(bottom, right);
.transform(180deg, -1, -1);
}
.image[orientation="270"][flipped*="vertical"][flipped*="horizontal"] .inline-image-info {
top: auto;
bottom: 100%;
left: auto;
right: auto;
.origin(bottom, right);
.transform(90deg, -1, -1);
}
/* XXX END */
.overlay-info {
display: none;
position: absolute;
bottom: 0px;
left: 0px;
width: 100%;
padding: 2px;
padding-left: 10px;
padding-right: 10px;
box-sizing: border-box;
background: black;
color: white;
opacity: 0.6;
}
.overlay-info:hover {
.user-select(auto);
}
.overlay-info .float-right {
float: right;
}
.overlay-info .secondary {
font-style: italic;
font-size: small;
color: silver;
}
.overlay-info::selection,
.overlay-info ::selection {
color: white;
background: red;
}
/*************************************************** Global status ***/
.global-status {
display: block;
opacity: 1;
z-index: 1000;
}
/****************************************************** Indicators ***/
.up-indicator,
.down-indicator,
.start-indicator,
.end-indicator,
.top-indicator,
.bottom-indicator
{
display: block;
position: absolute;
content: "";
top: 0px;
left: 50%;
height: 50px;
width: 100px;
margin-left: -50px;
overflow: hidden;
cursor: hand;
}
.up-indicator:after,
.down-indicator:after {
display: inline-block;
position: absolute;
content: "";
width: 50px;
height: 50px;
bottom: -25px;
left: 25px;
background: yellow;
.rotate(45deg);
}
.down-indicator {
top: auto;
bottom: 0px;
}
.down-indicator:after {
top: -25px;
bottom: auto;
}
.start-indicator,
.end-indicator {
left: 0px;
width: 10px;
height: 100%;
margin: 0px;
background: yellow;
}
.end-indicator {
left: auto;
right: 0px;
}
.top-indicator,
.bottom-indicator {
left: 0px;
height: 10px;
width: 100%;
margin: 0px;
background: yellow;
}
.bottom-indicator {
top: auto;
bottom: 0px;
}
/* default state */
.up-indicator,
.down-indicator,
.start-indicator,
.end-indicator,
.top-indicator,
.bottom-indicator
{
display: none;
}
/* these are generic containers for indicators */
.global-mode-indicators,
.context-mode-indicators {
position: absolute;
height: 20px;
width: auto;
min-width: 300px;
text-align: right;
color: transparent;
}
.global-mode-indicators {
top: 20px;
right: 20px;
}
.context-mode-indicators {
right: 20px;
bottom: 20px;
}
.global-mode-indicators .mode-tip,
.context-mode-indicators .mode-tip {
display: none;
opacity: 0.5;
font-weight: bold;
color: gray;
}
.global-mode-indicators:hover .mode-tip,
.context-mode-indicators:hover .mode-tip {
display: inline-block;
}
.global-mode-indicators > *,
.context-mode-indicators > * {
font-size: small;
vertical-align: center;
margin-left: 10px;
}
.global-mode-indicators .circle,
.context-mode-indicators .circle {
display: inline-block;
width: @single-image-indicator-size;
height: @single-image-indicator-size;
border-radius: 50%;
}
/* hide indicators in single image mode */
.single-image-mode.viewer .global-mode-indicators {
opacity: 0.5;
}
.light.single-image-mode.viewer .global-mode-indicators {
opacity: 0.1;
}
.dark.single-image-mode.viewer .global-mode-indicators {
opacity: 0.6;
}
.single-image-mode.viewer .global-mode-indicators:hover {
opacity: 1;
}
/* actual indicators */
/* marks... */
.global-mode-indicators .marked-only-visible,
.global-mode-indicators .marks-visible,
.context-mode-indicators .current-image-marked {
display: none;
color: blue;
height: 20px;
vertical-align: center;
}
.global-mode-indicators .marked-only-visible .shown,
.global-mode-indicators .marks-visible .shown,
.context-mode-indicators .current-image-marked .shown {
display: none;
}
.global-mode-indicators .marked-only-visible:after,
.global-mode-indicators .marks-visible:after,
.context-mode-indicators .current-image-marked:after {
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
content: "";
background-color: blue;
border: solid 2px blue;
margin-left: 5px;
margin-top: 3px;
top: 50%;
}
.marks-visible.viewer .global-mode-indicators .marks-visible {
display: inline-block;
}
.marked-only-view.viewer .global-mode-indicators .marks-visible {
display: none;
}
.marked-only-view.viewer .global-mode-indicators .marked-only-visible {
display: inline-block;
}
.marked-only-view.viewer:not(.marks-visible) .global-mode-indicators .marked-only-visible:after {
background-color: transparent;
}
/* image mark in single image mode... */
.context-mode-indicators .current-image-marked {
display: none;
color: blue;
}
.single-image-mode.marks-visible.viewer .context-mode-indicators .current-image-marked.shown {
display: inline-block;
}
/********************************************** Mode: single image ***/
.single-image-mode.viewer .image {
background-color: transparent;
/* NOTE: need to keep a distance from screen borders... */
border: solid transparent 2px;
}
.single-image-mode.viewer .image:not(.current) {
/* XXX for some reason this breaks the alignment on large magnifications...
display: none;
*/
/* XXX this makes images pass through the :visible filter...
opacity: 0;
*/
visibility: hidden;
}
/********************************************************** Themes ***/
/* XXX this is by no means final... */
.viewer,
.light.viewer,
.light.viewer .overlay-block .background {
background: white;
}
.gray.viewer,
.gray.viewer .overlay-block .background {
background: #333;
}
.dark.viewer,
.dark.viewer .overlay-block .background {
background: #0a0a0a;
}
/********************************************************* Overlay ***/
.overlay-block {
display: none;
position: absolute:
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
.viewer.overlay .overlay-block {
display: block;
}
.overlay-block .content {
}
.overlay-block .background {
position: absolute:
top: 0px;
left: 0px;
height: 100%;
width: 100%;
opacity: 0.7;
}
/************************************************************ Help ***/
/* XXX make this more generic, and not just for the keyboard... */
/* this is for sliding stuff */
.viewer.drawer-mode {
box-shadow: 0px 0px 50px 0px silver;
}
/* help */
.keyboard-help {
width: 80%;
margin-top: 20px;
margin-left: 15%;
margin-right: 5%;
margin-bottom: 100px;
}
.keyboard-help .section-doc {
font-size: small;
vertical-align: top;
font-style: italic;
}
.keyboard-help th {
text-align: left;
height: 50px;
vertical-align: bottom;
border-bottom: solid gray 1px;
}
.keyboard-help tr:hover {
background: #eee;
vertical-align: top;
}
.keyboard-help tr td:first-child {
color: gray;
font-style: italic;
padding-right: 20px;
padding-left: 10px;
}
.keyboard-help .section-doc td:only-child {
padding-right: 0px;
padding-left: 0px;
}
/**********************************************************************
* vim:set spell ft=css : */