1/* 2 * Copyright (c) 2022-2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15const { X2DFast } = require('./graphics/X2DFast'); 16const { Scr } = require('./XDefine'); 17const { XTools } = require('./XTools'); 18 19const MenuType = { 20 BUTTON: 0, // 按钮 21 CONTENT: 1, // 目录 22 DIVIDER: 2, // 分割线 23}; 24 25const MenuGroupSize = { 26 DELETE: 1, // 目录 27 NODEMENU: 3, // 分割线 28}; 29 30const MOUSETYPE_MOVE = 2; 31const DRAWTEXT_OFFSETX = -3; 32const DRAWTEXT_OFFSETY = -2; 33 34class RightMenu { 35 static backgroundImg_ = -1; 36 static backgroundCut_ = -1; 37 38 static popItemFocusImg_ = -1; 39 static popItemFocusCut_ = -1; 40 static MENU = null; 41 static PADDING = 16; 42 static FOCUS_ITEM_MARGIN = 4; 43 static FOCUS_ITEM_HEIGHT = 32; 44 static TEXT_SIZE = 14; 45 static isDarkBackground_ = true; 46 static Reset(detail, x, y) { 47 RightMenu.MENU = { 48 x: x === null ? XTools.MOUSE_POS.x : x, 49 y: y === null ? XTools.MOUSE_POS.y : y, 50 detail: detail, 51 needClose: false, 52 }; 53 } 54 static Append(detail) { 55 if (RightMenu.MENU) { 56 RightMenu.MENU.detail.push(...detail); 57 } 58 } 59 static Button(icon, name, hootkey, callback) { 60 return { 61 type: 0, 62 icon: icon, 63 name: name, 64 hk: hootkey, 65 cb: () => { 66 callback(this); 67 RightMenu.close(); 68 }, 69 }; 70 } 71 static Group(icon, name, objs) { 72 return { 73 type: 1, 74 icon: icon, 75 name: name, 76 open: false, 77 group: objs, 78 }; 79 } 80 static Gap() { 81 return { 82 type: 2, 83 }; 84 } 85 static close() { 86 if (RightMenu.MENU) { 87 RightMenu.MENU.needClose = true; 88 } 89 } 90 static Draw() { 91 if (RightMenu.MENU) { 92 RightMenu.DrawGroup( 93 RightMenu.MENU.detail, 94 RightMenu.MENU.x, 95 RightMenu.MENU.y 96 ); 97 if (RightMenu.MENU.needClose) { 98 RightMenu.MENU = null; 99 } 100 } 101 } 102 static MENUW = 155; 103 static DrawGroup(grp, x, y) { 104 let w = RightMenu.MENUW; 105 let l = 0; 106 for (let e of grp) { 107 if (e.type !== MenuType.DIVIDER) { 108 l += 1; 109 } 110 } 111 if (grp.length === MenuGroupSize.NODEMENU) { 112 X2DFast.px2f.drawCut(this.backgroundCut_, x, y, 1, 0.88, 0, -1, -1); 113 } else if (grp.length === MenuGroupSize.DELETE) { 114 X2DFast.px2f.drawCut(this.backgroundCut_, x, y, 1, 0.3, 0, -1, -1); 115 } else { 116 X2DFast.px2f.drawCut(this.backgroundCut_, x, y, 1, 1, 0, -1, -1); 117 } 118 for (let e of grp) { 119 e.rect = [x, y, w, 32]; 120 if (e.on) { 121 X2DFast.px2f.drawCut( 122 this.popItemFocusCut_, 123 x + RightMenu.FOCUS_ITEM_MARGIN, 124 y 125 ); 126 } 127 if (e.type === MenuType.DIVIDER) { 128 e.rect = [x, y, w, 0]; 129 X2DFast.px2f.drawLine(x, y, x + w, y, 0xff808080, 2); 130 continue; 131 } 132 let OFFY_ = y + RightMenu.FOCUS_ITEM_HEIGHT / 2 - RightMenu.TEXT_SIZE / 2; 133 let textColor = this.isDarkBackground_ ? 0xffffffff : 0xff000000; 134 X2DFast.px2f.drawText( 135 e.name, 136 RightMenu.TEXT_SIZE, 137 x + RightMenu.PADDING, 138 OFFY_, 139 1, 140 1, 141 0, 142 0, 143 0, 144 textColor 145 ); 146 if (e.type === MenuType.BUTTON) { 147 if (e.hk) { 148 X2DFast.px2f.drawText( 149 e.hk, 150 RightMenu.TEXT_SIZE, 151 x + w, 152 OFFY_, 153 1, 154 1, 155 0, 156 -3, 157 -2, 158 0xff808080 159 ); 160 } 161 } else if (e.type === MenuType.CONTENT) { 162 if (e.open) { 163 RightMenu.callDrawText('<', x, w, OFFY_, textColor); 164 RightMenu.DrawGroup(e.group, x + w, y); 165 } else { 166 RightMenu.callDrawText('>', x, w, OFFY_, textColor); 167 } 168 } 169 y += 32; 170 } 171 } 172 static callDrawText(symbol, x, w, OFFY_, textColor) { 173 X2DFast.px2f.drawText(symbol, RightMenu.TEXT_SIZE, x + w, OFFY_, 1, 1, 0, 174 DRAWTEXT_OFFSETX, DRAWTEXT_OFFSETY, textColor); 175 } 176 177 static Touch(msg, x, y) { 178 if (RightMenu.MENU) { 179 if (RightMenu.TouchGroup(RightMenu.MENU.detail, msg, x, y)) { 180 return true; 181 } else if (msg !== MOUSETYPE_MOVE) { 182 RightMenu.MENU.needClose = true; 183 } 184 } 185 return false; 186 } 187 188 isClicked() { 189 if (this.clicked_) { 190 this.clicked_ = false; 191 return true; 192 } 193 return false; 194 } 195 196 static TouchGroup(grp, msg, x, y) { 197 for (let e of grp) { 198 e.on = false; 199 } 200 for (let e of grp) { 201 if (!e.rect) { 202 return false; 203 } 204 if (XTools.InRect(x, y, ...e.rect)) { 205 if (e.type === MenuType.CONTENT && msg === 1) { 206 e.open = !e.open; 207 } 208 if (e.type === MenuType.DIVIDER) { 209 } 210 if (e.type === MenuType.BUTTON) { 211 if (msg === 1) { 212 e.cb(); 213 } 214 } 215 e.on = true; 216 return true; 217 } 218 if (e.type === MenuType.CONTENT) { 219 if (e.open && RightMenu.TouchGroup(e.group, msg, x, y)) { 220 return true; 221 } 222 } 223 } 224 return false; 225 } 226} 227 228module.exports = { 229 RightMenu, 230}; 231