ngui-tools
Version:
A GUI typesetting display engine and cross platform GUI application development framework based on NodeJS/OpenGL
392 lines (336 loc) • 10.6 kB
JSX
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2015, xuewen.chu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of xuewen.chu nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL xuewen.chu BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***** END LICENSE BLOCK ***** */
import {
View, Div, Text, Clip, Indep, ngui
} from './ngui';
import { Navigation } from './nav';
var arrow_size = { width: 30, height: 12 };
/**
* 获取left
*/
function get_left(self, x, offset_x) {
x -= 10; // 留出10像素边距
var screen_width = ngui.displayPort.width - 20;
var width = self.find('inl').clientWidth;
if (screen_width < width) {
return (screen_width - width) / 2 + 10;
}
else {
var left = x + offset_x / 2 - width / 2;
if (left < 0) {
left = 0;
}
else if(left + width > screen_width){
left = screen_width - width;
}
return left + 10;
}
}
/**
* 获取top
*/
function get_top(self, y, offset_y) {
y -= 10; // 留出10像素边距
var screen_height = ngui.displayPort.height - 20;
var height = self.find('inl').clientHeight;
if (screen_height < height) {
return (screen_height - height) / 2 + 10;
}
else{
var top = y + offset_y / 2 - height / 2;
if (top < 0) {
top = 0;
}
else if (top + height > screen_height) {
top = screen_height - height;
}
return top + 10;
}
}
/**
* 获取arrowtop
*/
function get_arrow_top(self, top, y, offset_y) {
var height = self.find('inl').clientHeight;
y += offset_y / 2;
var min = 8 + arrow_size.width / 2;
var max = height - 8 - arrow_size.width / 2;
if (min > max) {
return height / 2;
}
return Math.min(Math.max(min, y - top), max);
}
/**
* 获取arrowleft
*/
function get_arrow_left(self, left, x, offset_x) {
var width = self.find('inl').clientWidth;
x += offset_x / 2;
var min = 8 + arrow_size.width / 2;
var max = width - 8 - arrow_size.width / 2;
if (min > max) {
return width / 2;
}
return Math.min(Math.max(min, x - left), max);
}
/**
* 尝试在目标的top显示
*/
function attempt_top(self, x, y, offset_x, offset_y, force) {
var height = self.find('inl').clientHeight;
var top = y - height - arrow_size.height;
if (top - 10 > 0 || force) {
var left = get_left(self, x, offset_x);
var arrow_left = get_arrow_left(self, left, x, offset_x) - arrow_size.width / 2;
self.find('inl').style = { y: top, x: left };
self.find('arrow').style = {
alignX: 'left',
alignY: 'bottom',
y: arrow_size.height,// + 0.5,
x: arrow_left,
rotateZ: 180,
};
return true;
}
return false;
}
/**
* 尝试在目标的right显示
*/
function attempt_right(self, x, y, offset_x, offset_y, force) {
var width = self.find('inl').clientWidth;
var left = x + offset_x + arrow_size.height;
if (left + width + 10 <= ngui.displayPort.width || force) {
var top = get_top(self, y, offset_y);
var arrow_top = get_arrow_top(self, top, y, offset_y) - arrow_size.height / 2;
self.find('inl').style = { y: top, x: left };
self.find('arrow').style = {
alignX: 'left',
alignY: 'top',
x: -(arrow_size.width / 2 + arrow_size.height / 2),
y: arrow_top,
rotateZ: -90,
};
return true;
}
return false;
}
/**
* 尝试在目标的bottom显示
*/
function attempt_bottom(self, x, y, offset_x, offset_y, force){
var height = self.find('inl').clientHeight;
var top = y + offset_y + arrow_size.height;
if (top + height + 10 <= ngui.displayPort.height || force) {
var left = get_left(self, x, offset_x);
var arrow_left = get_arrow_left(self, left, x, offset_x) - arrow_size.width / 2;
self.find('inl').style = { y: top, x: left };
self.find('arrow').style = {
alignX: 'left',
alignY: 'top',
x: arrow_left,
y: -arrow_size.height,
rotateZ: 0,
};
return true;
}
return false;
}
/**
* 尝试在目标的left显示
*/
function attempt_left(self, x, y, offset_x, offset_y, force) {
var width = self.find('inl').clientWidth;
var left = x - width - arrow_size.height;
if (left - 10 > 0 || force) {
var top = get_top(self, y, offset_y);
var arrow_top = get_arrow_top(self, top, y, offset_y) - arrow_size.height / 2;
self.find('inl').style = { y: top, x: left };
self.find('arrow').style = {
alignX: 'right',
alignY: 'top',
x: arrow_size.width / 2 + arrow_size.height / 2,
y: arrow_top,
rotateZ: 90,
};
return true;
}
return false;
}
function showOverlay(self, x, y, offset_x, offset_y) {
switch (self.priority) {
case 'top':
attempt_top(self, x, y, offset_x, offset_y) ||
attempt_bottom(self, x, y, offset_x, offset_y) ||
attempt_right(self, x, y, offset_x, offset_y) ||
attempt_left(self, x, y, offset_x, offset_y) ||
attempt_top(self, x, y, offset_x, offset_y, true);
break;
case 'right':
attempt_right(self, x, y, offset_x, offset_y) ||
attempt_left(self, x, y, offset_x, offset_y) ||
attempt_bottom(self, x, y, offset_x, offset_y) ||
attempt_top(self, x, y, offset_x, offset_y) ||
attempt_right(self, x, y, offset_x, offset_y, true);
break;
case 'bottom':
attempt_bottom(self, x, y, offset_x, offset_y) ||
attempt_top(self, x, y, offset_x, offset_y) ||
attempt_right(self, x, y, offset_x, offset_y) ||
attempt_left(self, x, y, offset_x, offset_y) ||
attempt_bottom(self, x, y, offset_x, offset_y, true);
break;
default:
attempt_left(self, x, y, offset_x, offset_y) ||
attempt_right(self, x, y, offset_x, offset_y) ||
attempt_bottom(self, x, y, offset_x, offset_y) ||
attempt_top(self, x, y, offset_x, offset_y) ||
attempt_left(self, x, y, offset_x, offset_y, true);
break;
}
}
/**
* @class Overlay
*/
export class Overlay extends Navigation {
m_is_activate = false;
/**
* 默认为点击屏幕任何位置都会消失
*/
frail = true;
m_pos_x = 0;
m_pos_y = 0;
m_offset_x = 0;
m_offset_y = 0;
/**
* 优先显示的位置
*/
priority = 'bottom'; // top | right | bottom | left
get backgroundColor() {
return this.find('content').backgroundColor;
}
set backgroundColor(value) {
this.find('arrow_text').textColor = value;
this.find('content').backgroundColor = value;
}
/**
* @overwrite
*/
loadView(vx) {
super.loadView(
<Indep visible=0 width="full" height="full" backgroundColor="#0003" opacity=0>
<Div width="full" height="full"
onTouchStart="fadeOut" id="mask" />
<Indep id="inl">
<Indep id="arrow"
width=arrow_size.width
height=arrow_size.height
originX=(arrow_size.width/2) originY=(arrow_size.height/2)>
<Text id="arrow_text"
y=-10 x=-3
textFamily='icon'
textLineHeight="auto"
textSize=36 textColor="#fff" value="\uedc7" />
</Indep>
<Clip id="content" backgroundColor="#fff" borderRadius=8>
${vx}
</Clip>
</Indep>
</Indep>
);
//ngui.displayPort.onChange.on(self.remove, self);
this.find('inl').onClick.on(()=>{
if ( this.frail ) {
this.fadeOut();
}
});
this.view.appendTo(ngui.root);
}
fadeOut() {
this.transition({ opacity: 0, time: 200 }, ()=>{
this.remove();
});
this.unregisterNavigation(0, null);
}
/**
* @fun showOverlayWithView(target_view[,offset_x[,offset_y]]) 通过目标视图显示 Overlay
* @arg target_view {View} # 参数可提供要显示的位置信息
* @arg [offset] {Object} # 显示目标位置的偏移
*/
showOverlayWithView(target_view, offset_x, offset_y) {
offset_x = offset_x || 0;
offset_y = offset_y || 0;
var rect = target_view.screenRect();
this.showOverlay(
rect.x + offset_x, rect.y + offset_y,
rect.width - offset_x * 2, rect.height - offset_y * 2);
}
/**
* showOverlay(pos_x,pos_y[,offset_x[,offset_y]]) 通过位置显示
*/
showOverlay(pos_x, pos_y, offset_x, offset_y) {
var self = this;
var x = Math.max(0, Math.min(ngui.displayPort.width, pos_x));
var y = Math.max(0, Math.min(ngui.displayPort.height, pos_y));
offset_x = offset_x || 0;
offset_y = offset_y || 0;
self.show();
self.m_x = x;
self.m_y = y;
self.m_offset_x = offset_x;
self.m_offset_y = offset_y;
ngui.nextFrame(function() {
showOverlay(self, x, y, offset_x, offset_y);
self.transition({ opacity: 1, time: 200 });
});
self.m_is_activate = true;
this.registerNavigation(0);
}
/**
* reset() 重新设置位置
*/
reset() {
if (this.m_is_activate) {
showOverlay(this, this.m_pos_x, this.m_pos_y, this.m_offset_x, this.m_offset_y);
}
}
/**
* @overwrite
*/
navigationBack() {
this.fadeOut();
return true;
}
/**
* @overwrite
*/
navigationEnter(focus) {
}
}