359 lines
15 KiB
JavaScript
359 lines
15 KiB
JavaScript
|
|
function newUiObjectTitle() {
|
|
const MODULE_NAME = 'UI Object Title'
|
|
const ERROR_LOG = true
|
|
|
|
const logger = newWebDebugLog()
|
|
logger.fileName = MODULE_NAME
|
|
|
|
let thisObject = {
|
|
fitFunction: undefined,
|
|
isVisibleFunction: undefined,
|
|
allwaysVisible: undefined,
|
|
editMode: undefined,
|
|
container: undefined,
|
|
payload: undefined,
|
|
isDefault: undefined,
|
|
enterEditMode: enterEditMode,
|
|
exitEditMode: exitEditMode,
|
|
physics: physics,
|
|
draw: draw,
|
|
getContainer: getContainer,
|
|
finalize: finalize,
|
|
initialize: initialize
|
|
}
|
|
|
|
thisObject.container = newContainer()
|
|
thisObject.container.initialize(MODULE_NAME)
|
|
thisObject.container.isClickeable = true
|
|
thisObject.container.isDraggeable = false
|
|
thisObject.container.frame.radius = 0
|
|
|
|
let selfFocusEventSubscriptionId
|
|
let selfNotFocuskEventSubscriptionId
|
|
let selfMouseClickEventSubscriptionId
|
|
|
|
return thisObject
|
|
|
|
function finalize() {
|
|
thisObject.container.eventHandler.stopListening(selfFocusEventSubscriptionId)
|
|
thisObject.container.eventHandler.stopListening(selfNotFocuskEventSubscriptionId)
|
|
thisObject.container.eventHandler.stopListening(selfMouseClickEventSubscriptionId)
|
|
|
|
thisObject.container.finalize()
|
|
thisObject.container = undefined
|
|
thisObject.payload = undefined
|
|
thisObject.isVisibleFunction = undefined
|
|
thisObject.fitFunction = undefined
|
|
}
|
|
|
|
function initialize(payload) {
|
|
thisObject.payload = payload
|
|
|
|
thisObject.allwaysVisible = false // Default value
|
|
let nodeDefinition = getNodeDefinition(thisObject.payload.node)
|
|
if (nodeDefinition !== undefined) {
|
|
if (nodeDefinition.isTitleAllwaysVisible === true) {
|
|
thisObject.allwaysVisible = true
|
|
}
|
|
}
|
|
|
|
selfFocusEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onFocus', onFocus)
|
|
selfNotFocuskEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onNotFocus', onNotFocus)
|
|
selfMouseClickEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
|
}
|
|
|
|
function getContainer(point) {
|
|
if (AT_FULL_SCREEN_MODE === true) { return } // Fullscreen mode does not allow INPUT elements
|
|
|
|
let container
|
|
|
|
if (thisObject.editMode === true) {
|
|
if (point.x === VERY_LARGE_NUMBER) {
|
|
/* The the mouse leaves the canvas, and event of mouse over with a ridiculous coordinate is triggered so that
|
|
anyone can react. In our case, this object has an html input element that is not part of the canvas, so the event is
|
|
triggered. We compensate recognizing this coordinate and returning our container. */
|
|
return thisObject.container
|
|
}
|
|
}
|
|
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
|
return thisObject.container
|
|
} else {
|
|
return undefined
|
|
}
|
|
}
|
|
|
|
function physics() {
|
|
inheritancePhysics()
|
|
defaultPhysics()
|
|
}
|
|
|
|
function defaultPhysics() {
|
|
if (thisObject.payload.title !== 'New ' + thisObject.payload.node.type && thisObject.payload.title !== 'My ' + thisObject.payload.node.type) {
|
|
thisObject.isDefault = false
|
|
} else {
|
|
thisObject.isDefault = true
|
|
}
|
|
}
|
|
|
|
function inheritancePhysics() {
|
|
if (thisObject.payload.title === undefined) { return }
|
|
|
|
/* It is possible to override the default title by setting the APP SCHEMA property 'title' */
|
|
let nodeDefinition = getNodeDefinition(thisObject.payload.node)
|
|
if (nodeDefinition.title !== undefined) {
|
|
thisObject.payload.title = ''
|
|
thisObject.payload.node.name = ''
|
|
let separator = ''
|
|
for (let i = 0; i < nodeDefinition.title.length; i++) {
|
|
let titleReference = nodeDefinition.title[i]
|
|
switch (titleReference) {
|
|
case 'Use Reference Parent': {
|
|
let nodeToUse = thisObject.payload.node.payload.referenceParent
|
|
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
|
thisObject.payload.title = thisObject.payload.title + separator + nodeToUse.payload.title
|
|
thisObject.payload.node.name = thisObject.payload.node.name + separator + nodeToUse.payload.node.name
|
|
}
|
|
break
|
|
}
|
|
case 'Use Reference Grandparent': {
|
|
let nodeToUse = thisObject.payload.node.payload.referenceParent
|
|
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
|
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.referenceParent
|
|
if (nodeToUse !== undefined) {
|
|
thisObject.payload.title = thisObject.payload.title + separator + nodeToUse.payload.title
|
|
thisObject.payload.node.name = thisObject.payload.node.name + separator + nodeToUse.payload.node.name
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'Use Reference Parent Parent': {
|
|
let nodeToUse = thisObject.payload.node.payload.referenceParent
|
|
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
|
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode
|
|
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
|
thisObject.payload.title = thisObject.payload.title + separator + nodeToUse.payload.title
|
|
thisObject.payload.node.name = thisObject.payload.node.name + separator + nodeToUse.payload.node.name
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'Use Reference Parent Parent Parent': {
|
|
let nodeToUse = thisObject.payload.node.payload.referenceParent
|
|
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
|
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode
|
|
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
|
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode.payload.parentNode
|
|
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
|
thisObject.payload.title = thisObject.payload.title + separator + nodeToUse.payload.title
|
|
thisObject.payload.node.name = thisObject.payload.node.name + separator + nodeToUse.payload.node.name
|
|
}
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'Use Reference Parent Parent Parent': {
|
|
let nodeToUse = thisObject.payload.node.payload.referenceParent
|
|
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
|
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode
|
|
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
|
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode.payload.parentNode
|
|
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
|
thisObject.payload.title = thisObject.payload.title + separator + nodeToUse.payload.title
|
|
thisObject.payload.node.name = thisObject.payload.node.name + separator + nodeToUse.payload.node.name
|
|
}
|
|
}
|
|
}
|
|
break
|
|
}
|
|
default: {
|
|
if (titleReference.indexOf('Use Child @') === 0) {
|
|
let propertyName = titleReference.substring(titleReference.indexOf('@') + 1, titleReference.length)
|
|
let childNode = thisObject.payload.node[propertyName]
|
|
if (childNode === undefined) { break }
|
|
thisObject.payload.title = thisObject.payload.title + separator + childNode.name
|
|
thisObject.payload.node.name = thisObject.payload.node.name + separator + childNode.name
|
|
}
|
|
}
|
|
}
|
|
separator = ' '
|
|
}
|
|
}
|
|
|
|
/* The name becomes the title. */
|
|
if (thisObject.payload.node.name !== undefined) {
|
|
thisObject.payload.title = thisObject.payload.node.name
|
|
}
|
|
|
|
let title = trimTitle(thisObject.payload.title)
|
|
|
|
/* Here we set the dimensions and position of this object */
|
|
const FRAME_HEIGHT = 25
|
|
const Y_OFFSET = -20
|
|
const FRAME_WIDTH = (title.length + 2) / 2 * thisObject.payload.floatingObject.currentFontSize * FONT_ASPECT_RATIO * 1.2 * 2
|
|
thisObject.container.frame.position.x = 0 - FRAME_WIDTH / 2
|
|
thisObject.container.frame.position.y = 0 - thisObject.container.frame.radius * 1 / 2 - thisObject.payload.floatingObject.currentFontSize * FONT_ASPECT_RATIO + Y_OFFSET - FRAME_HEIGHT
|
|
|
|
thisObject.container.frame.width = FRAME_WIDTH
|
|
thisObject.container.frame.height = FRAME_HEIGHT
|
|
|
|
if (thisObject.editMode === true) {
|
|
let inputPosition = {
|
|
x: 0,
|
|
y: 0 + CURRENT_TOP_MARGIN + Y_OFFSET
|
|
}
|
|
|
|
inputPosition = thisObject.container.frame.frameThisPoint(inputPosition)
|
|
|
|
if (inputPosition.y < CURRENT_TOP_MARGIN) { exitEditMode() }
|
|
|
|
let inputDiv = document.getElementById('inputDiv')
|
|
inputDiv.style = 'position:absolute; top:' + inputPosition.y + 'px; left:' + inputPosition.x + 'px; z-index:1; '
|
|
}
|
|
}
|
|
|
|
function onFocus() {
|
|
thisObject.isOnFocus = true
|
|
}
|
|
|
|
function onNotFocus() {
|
|
thisObject.isOnFocus = false
|
|
exitEditMode()
|
|
}
|
|
|
|
function onMouseClick(event) {
|
|
let nodeDefinition = getNodeDefinition(thisObject.payload.node)
|
|
if (nodeDefinition.title !== undefined) { return }
|
|
|
|
let checkPoint = {
|
|
x: 0,
|
|
y: 0
|
|
}
|
|
checkPoint = thisObject.container.frame.frameThisPoint(checkPoint)
|
|
|
|
if (thisObject.isVisibleFunction(checkPoint) === true) {
|
|
enterEditMode()
|
|
}
|
|
}
|
|
|
|
function exitEditMode() {
|
|
if (thisObject.editMode === true) {
|
|
thisObject.editMode = false
|
|
let input = document.getElementById('input')
|
|
input.style.display = 'none'
|
|
if (input.value.length > 2) {
|
|
thisObject.payload.title = input.value
|
|
thisObject.payload.node.name = input.value
|
|
}
|
|
}
|
|
let inputDiv = document.getElementById('inputDiv')
|
|
inputDiv.style = 'position:absolute; top:' + '-100' + 'px; left:' + '-100' + 'px; z-index:1; '
|
|
}
|
|
|
|
function enterEditMode() {
|
|
const WIDTH = thisObject.container.frame.width
|
|
const HEIGHT = thisObject.container.frame.height
|
|
let fontSize = thisObject.payload.floatingObject.currentFontSize
|
|
|
|
thisObject.editMode = true
|
|
let input = document.getElementById('input')
|
|
input.value = thisObject.payload.title
|
|
|
|
let backgroundColor = '0, 0, 0'
|
|
if (thisObject.payload.uiObject.codeEditor !== undefined) {
|
|
if (thisObject.payload.uiObject.codeEditor.visible === true) {
|
|
backgroundColor = '204, 88, 53'
|
|
}
|
|
}
|
|
|
|
input.style = 'resize: none; border: none; outline: none; box-shadow: none; overflow:hidden; font-family: Saira Condensed; font-size: ' + fontSize + 'px; background-color: rgb(' + backgroundColor + ');color:rgb(255, 255, 255); width: ' + WIDTH + 'px; height: ' + HEIGHT + 'px'
|
|
input.style.display = 'block'
|
|
input.focus()
|
|
}
|
|
|
|
function draw() {
|
|
if (thisObject.isOnFocus === true || thisObject.allwaysVisible === true || thisObject.isDefault === false) {
|
|
if (thisObject.payload.uiObject.codeEditor !== undefined) {
|
|
if (thisObject.payload.uiObject.codeEditor.visible !== true) {
|
|
drawTitleBackground()
|
|
}
|
|
} else {
|
|
drawTitleBackground()
|
|
}
|
|
|
|
drawText()
|
|
}
|
|
}
|
|
|
|
function drawTitleBackground() {
|
|
if (thisObject.editMode !== true) {
|
|
let params = {
|
|
cornerRadius: 3,
|
|
lineWidth: 0.1,
|
|
container: thisObject.container,
|
|
borderColor: UI_COLOR.BLACK,
|
|
backgroundColor: UI_COLOR.BLACK,
|
|
castShadow: false,
|
|
opacity: 0.25
|
|
}
|
|
|
|
roundedCornersBackground(params)
|
|
}
|
|
}
|
|
|
|
function drawText() {
|
|
if (thisObject.editMode !== true) {
|
|
let radius = thisObject.container.frame.radius
|
|
let labelPoint
|
|
let fontSize = thisObject.payload.floatingObject.currentFontSize
|
|
let label
|
|
|
|
if (radius > 6 && (thisObject.isOnFocus === true || thisObject.allwaysVisible === true || thisObject.isDefault === false)) {
|
|
browserCanvasContext.strokeStyle = thisObject.payload.floatingObject.labelStrokeStyle
|
|
|
|
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
|
|
|
label = thisObject.payload.title
|
|
|
|
if (label !== undefined) {
|
|
label = trimTitle(label)
|
|
|
|
labelPoint = {
|
|
x: 5,
|
|
y: thisObject.container.frame.height * 0.8
|
|
}
|
|
|
|
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint)
|
|
|
|
if (canvas.floatingSpace.inMapMode === true) {
|
|
labelPoint = canvas.floatingSpace.transformPointToMap(labelPoint)
|
|
labelPoint.x = labelPoint.x - label.length / 2 * fontSize * FONT_ASPECT_RATIO
|
|
labelPoint.y = labelPoint.y - 35
|
|
|
|
let nodeDefinition = getNodeDefinition(thisObject.payload.node)
|
|
if (nodeDefinition !== undefined) {
|
|
if (nodeDefinition.isHierarchyHead !== true) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
|
browserCanvasContext.fillStyle = thisObject.payload.floatingObject.labelStrokeStyle
|
|
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function trimTitle(title) {
|
|
if (title === undefined) { return }
|
|
const MAX_LABEL_LENGTH = 50
|
|
if (title.length > MAX_LABEL_LENGTH) {
|
|
title = title.substring(0, MAX_LABEL_LENGTH) + '...'
|
|
}
|
|
return title
|
|
}
|
|
}
|
|
|