...
 
Commits (160)
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
name: Go
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: '1.18'
- name: Test
run:
go test -v -coverprofile="cover.out" -covermode=atomic ./...
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: "cover.out"
flags: unittests
verbose: true
......@@ -124,7 +124,11 @@ bytes.txt
*.icns
icons.iconset/
energy-*
dist
EnergyFramework
EnergyFrameworkDownloadCache
ssl
\ No newline at end of file
ssl
testdata
\ No newline at end of file
......@@ -4,7 +4,7 @@
<p align="center" style="font-size: 24px;">
<strong>
Energy is framework for Go to build desktop applications based on CEF
Energy is a framework for Go to build desktop applications based on CEF
</strong>
</p>
......@@ -12,102 +12,86 @@
English
---
![go-version](https://img.shields.io/github/go-mod/go-version/energye/energy?logo=git&logoColor=green)
[![github](https://img.shields.io/github/last-commit/energye/energy/main.svg?logo=github&logoColor=green&label=commit)](https://github.com/energye/energy)
[![release](https://img.shields.io/github/v/release/energye/energy?logo=git&logoColor=green)](https://github.com/energye/energy/releases)
[![license](https://img.shields.io/github/license/energye/energy.svg?logo=git&logoColor=red)](http://www.apache.org/licenses/LICENSE-2.0)
![Build Status](https://github.com/energye/energy/actions/workflows/go.yml/badge.svg)
![repo](https://img.shields.io/github/repo-size/energye/energy.svg?logo=github&logoColor=green&label=repo-size)
![go-version](https://img.shields.io/github/go-mod/go-version/energye/energy?logo=git&logoColor=green)
[![Go Report](https://goreportcard.com/badge/github.com/energye/energy)](https://goreportcard.com/report/github.com/energye/energy/v2)
[![Go Reference](https://pkg.go.dev/badge/github.com/energye/energy)](https://pkg.go.dev/github.com/energye/energy/v2)
[![codecov](https://codecov.io/gh/energye/energy/graph/badge.svg?token=H370UFUF12)](https://codecov.io/gh/energye/energy)
[![contributors](https://img.shields.io/github/contributors/energye/energy)](https://github.com/energye/energy/graphs/contributors)
[![license](https://img.shields.io/github/license/energye/energy.svg?logo=git&logoColor=red)](http://www.apache.org/licenses/LICENSE-2.0)
---
### [Project Introduction](https://energy.yanghy.cn/course/100/6350f94ca749ba0318943f25)
Energy is a framework developed by Golang based on CEF(Chromium Embedded Framework), embedded
with [CEF](https://bitbucket.org/chromiumembedded/cef) binary
Energy is a framework by Golang based on CEF(Chromium Embedded Framework), embedded
[CEF](https://bitbucket.org/chromiumembedded/cef) binary
> [energy](https://github.com/energye/energy) is a framework developed by Golang based on CEF(Chromium Embedded
> Framework), embedded with [CEF](https://bitbucket.org/chromiumembedded/cef) binary
>
> Use Go and Web technology (HTML+CSS+JavaScript) to build cross-platform desktop applications that support Windows,
> Linux and MacOS
>
> Knowledge of the front-end technology stack and some knowledge of the Go language is required
### Characteristic
> - Rich CEF API and LCL system native widgets
> - development environment is simple and the compilation speed is fast. Only the Go development environment and the CEF
binary framework that Energy depends on are needed
> - cross-platform: A set of code can be packaged into Windows, domestic UOS, Deepin, Kylin, MacOS, Linux
> - Language responsibilities
>> - Go: Go is responsible for window creation, CEF configuration and function implementation, creation of various UI
components, low-level system calls, and functions that JS cannot handle, such as file stream, security encryption,
high-performance processing, etc.
>> - Web: HTML + CSS + JavaScript responsible for the function of the client interface, make any interface you want, Any front-end technology framework can be used
> - front-end technology: Support mainstream front-end frameworks, such as Vue, React, Angular or pure HTML+CSS
> - event driven: High performance event driven, IPC based communication, Go and Web side is very convenient function
call and data interaction
> - resource loading: supports local or built-in to executable files, http service support is not required, multiple choices.
> - Development environment is simple and the compilation speed is fast. Only need Go and Energy.
> - Cross-Platform: You can package your code as Windows, domestic UOS, Deepin, Kylin, MacOS and Linux
> - Responsibilities
>> - Go: Go is responsible for creating Windows, configuring CEF and implementing functions, creating various UI components, calling the low level of the system and some functions that JS cannot handle, such as: file flow, security encryption, high-performance processing, etc.
>> - Web: HTML + CSS + JavaScript is responsible for the function of the client interface, you can make any interface you want.
> - Front-end technology: Support mainstream frameworks, such as Vue, React, Angular or pure HTML+CSS+JS.
> - Event driven: High performance event driven, based on IPC communication, Go and Web can call each other quality.
> - Esource loading: You can either read local resources or resources build into execution files without http services, or you can load resources using http services.
### Built-in dependency&integration
- [![LCL](https://img.shields.io/badge/LCL-green)](https://github.com/energye/golcl)
- [![CEF-CEF4Delphi](https://img.shields.io/badge/CEF(Chromium%20Embedded%20Framework)%20CEF4Delphi-green)](https://github.com/salvadordf/CEF4Delphi)
### [Development environment](https://energy.yanghy.cn/course/100/63511b14a749ba0318943f3a)
> Install automatically using the energy command line tool
### [Development Environment](https://energy.yanghy.cn/course/100/63511b14a749ba0318943f3a)
#### Basic needs
> - golang >= 1.18
>
> - energy development environment
>
> Use the energy command line tool to automatically install the development environment
>
> Get [energy](https://github.com/energye/energy) project, or use the precompiled command line tool
> directly [Download address](https://energy.yanghy.cn/course/100/63511b14a749ba0318943f3a)
>
> <p style="color:palevioletred;">If using pre compiled command-line tools, the following steps can be skipped</p>
>
> `git clone https://github.com/energye/energy.git`
>
> Enter the [energy](https://github.com/energye/energy) command line directory
>
> `cd energy/cmd/energy`
>
> Install command line tools
>
> `go install`
>
> Execute the installation command
> - Golang >= 1.18
> - Energy (CEF, liblcl)
#### Environmental installation
- Automatic installation development environment
> Using the energy command-line tool [Download address](https://energy.yanghy.cn/course/100/1694511322285207)
>
> `energy install .`
> During the installation process, you can optionally install the following frameworks and tools, or you can download the resources yourself.
### Getting Started Guide - [Transfer gate](https://energy.yanghy.cn)
| Name | Platform | illustrate |
|-------------|----------------|----------------------------------------------|
| Golang | ALL | Golang Development Environment |
| CEF, liblcl | ALL | CEF Framework |
| NSIS | Windows | Windows Installation package production tool |
| UPX | All | Execute file compression tool |
| 7z | Windows, Linux | CEF Framework compression tool |
### Guide to Start - [Link](https://energy.yanghy.cn)
* [Course](https://energy.yanghy.cn/course/100/0)
* [Example](https://energy.yanghy.cn/example/200/0)
* [Document](https://energy.yanghy.cn/document/300/0)
### Quick Get Start
### Quick Start
> Must: You need to install the Go development environment yourself [Golang Install](https://golang.google.cn/dl/)
>
> Use [energy-command-line](https://energy.yanghy.cn/course/100/63511b14a749ba0318943f3a) Command line tool automatic
> installation environment dependency
>
> `energy install .`
>
> Take example/simple as an example
>
> Update latest release dependency
>
> `go mod tidy`
>
> Run `simple` in the IDE or `go run simple.go`
> Using [energy](https://energy.yanghy.cn/course/100/1694511322285207) Command line tools to install the complete development environment automatically.
### Run a simple application by three steps
1. Install development environment: `energy install .`
2. Initiate an Application: `energy init .`
3. Run the Application: `go run main.go`
### sample code
### example/simple Code
main.go
```go
package main
......@@ -117,31 +101,25 @@ import (
)
func main() {
//Global initialization must be called by every application
//Global initialization
cef.GlobalInit(nil, nil)
//Create application
cefApp := cef.NewApplication()
//Set URL
cef.BrowserWindow.Config.Url = "https://www.yanghy.cn"
//Run App
cef.Run(cefApp)
//Create an application
app := cef.NewApplication()
//Specify a URL address or local HTML file directory
cef.BrowserWindow.Config.Url = "https://energy.yanghy.cn"
//Run Application
cef.Run(app)
}
```
---
### Run app
- Windows、Linux
> `go run simple.go`
- MacOS
### Build
1. Build:`energy build .`
2. Package:`energy package .`
3. Package Type:
- windows Using`nsis`Create exe installation package
- linux Using`dpkg`Create deb installation package
- macos Generate`xxx.app`
> `go run simple.go energy_env=dev`
---
### System support
......@@ -157,6 +135,14 @@ func main() {
| Linux | ![Linux](https://img.shields.io/badge/SelfCompila-supported-success.svg?logo=Linux) | ![Linux](https://img.shields.io/badge/supported-success.svg?logo=Linux&logoColor=red) | Deepin20.8、Ubuntu18.04、LinuxMint21 |
| Linux ARM | ![Linux ARM](https://img.shields.io/badge/SelfCompila-supported-success.svg?logo=Linux) | ![Linux ARM](https://img.shields.io/badge/SelfCompila-supported-success.svg?logo=Linux) | Kylin-V10-SP1-2107 |
### Related Projects
* [CEF](https://github.com/chromiumembedded/cef)
* [CEF4Delphi](https://github.com/salvadordf/CEF4Delphi)
* [CefSharp](https://github.com/cefsharp/CefSharp)
* [Java-CEF](https://bitbucket.org/chromiumembedded/java-cef)
* [cefpython](https://github.com/cztomczak/cefpython)
* [Chromium](https://chromium.googlesource.com/chromium/src/)
---
### Thanks Jetbrains
......@@ -167,7 +153,8 @@ func main() {
</a>
</p>
Thank you for ordering a Star for the project
If this project is helpful to you, please give me a star
---
......
......@@ -12,13 +12,16 @@
[English](README.md)
---
![go-version](https://img.shields.io/github/go-mod/go-version/energye/energy?logo=git&logoColor=green)
[![github](https://img.shields.io/github/last-commit/energye/energy/main.svg?logo=github&logoColor=green&label=commit)](https://github.com/energye/energy)
[![release](https://img.shields.io/github/v/release/energye/energy?logo=git&logoColor=green)](https://github.com/energye/energy/releases)
[![license](https://img.shields.io/github/license/energye/energy.svg?logo=git&logoColor=red)](http://www.apache.org/licenses/LICENSE-2.0)
![Build Status](https://github.com/energye/energy/actions/workflows/go.yml/badge.svg)
![repo](https://img.shields.io/github/repo-size/energye/energy.svg?logo=github&logoColor=green&label=repo-size)
![go-version](https://img.shields.io/github/go-mod/go-version/energye/energy?logo=git&logoColor=green)
[![Go Report](https://goreportcard.com/badge/github.com/energye/energy)](https://goreportcard.com/report/github.com/energye/energy/v2)
[![Go Reference](https://pkg.go.dev/badge/github.com/energye/energy)](https://pkg.go.dev/github.com/energye/energy/v2)
[![codecov](https://codecov.io/gh/energye/energy/graph/badge.svg?token=H370UFUF12)](https://codecov.io/gh/energye/energy)
[![contributors](https://img.shields.io/github/contributors/energye/energy)](https://github.com/energye/energy/graphs/contributors)
[![license](https://img.shields.io/github/license/energye/energy.svg?logo=git&logoColor=red)](http://www.apache.org/licenses/LICENSE-2.0)
---
### [项目简介](https://energy.yanghy.cn/course/100/6350f94ca749ba0318943f25)
......@@ -27,20 +30,19 @@
> 开发的框架,内嵌 [CEF](https://bitbucket.org/chromiumembedded/cef) 二进制
>
> 使用 Go 和 Web 端技术 ( HTML + CSS + JavaScript ) 构建支持Windows, Linux, MacOS跨平台桌面应用
>
> 需要会前端技术栈和略懂Go语言
### 特性
> - 具有丰富的CEF API 和 LCL 系统原生小部件
> - 开发环境简单,编译速度快,只需要Go和Energy依赖的CEF二进制框架
> - 开发环境简单,编译速度快,仅需Go和Energy依赖的CEF二进制框架
> - 跨平台: 一套代码可以打包成 Windows, 国产UOS、Deepin、Kylin, MacOS, Linux
> - 语言职责
>> - Go: Go负责窗口创建、CEF配置和功能实现、各种UI组件创建、系统低层调用,和JS处理不了的功能如: 文件流、安全加密、高性能处理等
> - 职责
>> - Go: Go负责窗口创建、CEF配置和功能实现、各种UI组件创建、系统低层调用和JS处理不了的功能,如: 文件流、安全加密、高性能处理
>> - Web: HTML + CSS + JavaScript 负责客户端界面的功能, 做出任意你想要的界面
> - 前端技术: 支持主流前端框架例如:Vue、React、Angular, 或纯HTML+CSS等
> - 事件驱动: 高性能事件驱动, 基于IPC通信,实现Go和Web端很方便功能调用以及数据交互
> - 资源加载: 支持本地或内置到执行文件, 不需要http服务支撑, 多种选择
> - 前端技术: 支持主流前端框架。例如:Vue、React、Angular 和 原生HTML+CSS+JS
> - 事件驱动: 高性能事件驱动, 基于IPC通信,实现Go和Web端迅捷调用及数据交互
> - 资源加载: 可无需http服务支撑,直接读取本地资源或内置到执行文件的资源, 也支持http服务加载资源
### 内置依赖&集成
......@@ -52,27 +54,23 @@
#### 基本需求
> - Golang >= 1.18
> - Energy 开发环境
>
> 使用 energy 命令行工具自动安装开发环境
>
> 获取 [energy](https://github.com/energye/energy) 项目,或直接使用预编译命令行工具 [下载地址](https://energy.yanghy.cn/course/100/63511b14a749ba0318943f3a)
>
> <p style="color:palevioletred;">如果使用预编译命令行工具以下步骤可跳过</p>
>
> `git clone https://github.com/energye/energy.git`
>
> 进入 energy 命令行目录
>
> `cd energy/cmd/energy`
>
> 安装命令行工具
>
> `go install`
>
> 执行安装命令
> - Energy 开发环境(CEF, liblcl)
#### 环境安装
- 自动安装开发环境
> 使用 energy 命令行工具自动安装完整开发环境 [命令行工具下载地址](https://energy.yanghy.cn/course/100/1694511322285207)
>
> `energy install .`
> 此安装过程可选择性安装以下框架和工具,也可自行下载资源
| 名称 | 平台 | 说明 |
|-------------|----------------|----------------|
| Golang | ALL | Go语言开发环境 |
| CEF, liblcl | ALL | CEF框架 |
| NSIS | Windows | Windows安装包制作工具 |
| UPX | ALL | 执行文件压缩工具 |
| 7z | Windows, Linux | CEF框架压缩工具 |
### 入门指南 - [传送门](https://energy.yanghy.cn)
......@@ -81,21 +79,18 @@
* [文档](https://energy.yanghy.cn/document/300/0)
### 快速入门
> 必须: 你需要自己安装Go开发环境 [Golang安装包](https://golang.google.cn/dl/)
>
> 使用 [energy-command-line](https://energy.yanghy.cn/course/100/63511b14a749ba0318943f3a) 命令行工具自动安装开发环境依赖
>
> `energy install .`
>
> 以example/simple示例为例
>
> 更新最新发布版本依赖
>
> `go mod tidy`
>
> 在IDE中运行 simple 或 go run simple.go
### example/simple 示例代码
> 使用 [energy](https://energy.yanghy.cn/course/100/1694511322285207) 命令行工具自动安装完整开发环境
### 三个步骤运行一个简单应用
1. 安装开发环境: `energy install .`
2. 初始化应用: `energy init .`
3. 运行应用: `go run main.go`
### 示例代码
main.go
```go
package main
......@@ -105,23 +100,24 @@ import (
)
func main() {
//全局初始化 每个应用都必须调用的
//全局初始化
cef.GlobalInit(nil, nil)
//创建应用
cefApp := cef.NewApplication()
app := cef.NewApplication()
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "https://energy.yanghy.cn"
//运行应用
cef.Run(cefApp)
cef.Run(app)
}
```
---
### 运行应用
- Windows、Linux
> `go run simple.go`
- MacOS
> `go run simple.go energy_env=dev`
### 应用打包
1. 编译:`energy build .`
2. 打包:`energy package .`
3. 自动生成的安装包
- windows 使用`nsis`工具生成exe安装包
- linux 使用`dpkg`制作deb安装包
- macos 生成`xxx.app`
### 系统支持
......@@ -138,6 +134,14 @@ func main() {
| Linux | ![Linux](https://img.shields.io/badge/自编译-supported-success.svg?logo=Linux) | ![Linux](https://img.shields.io/badge/supported-success.svg?logo=Linux&logoColor=red) | Deepin20.8、Ubuntu18.04、LinuxMint21 |
| Linux ARM | ![Linux ARM](https://img.shields.io/badge/自编译-supported-success.svg?logo=Linux) | ![Linux ARM](https://img.shields.io/badge/自编译-supported-success.svg?logo=Linux) | Kylin-V10-SP1-2107 |
### 相关项目
* [CEF](https://github.com/chromiumembedded/cef)
* [CEF4Delphi](https://github.com/salvadordf/CEF4Delphi)
* [CefSharp](https://github.com/cefsharp/CefSharp)
* [Java-CEF](https://bitbucket.org/chromiumembedded/java-cef)
* [cefpython](https://github.com/cztomczak/cefpython)
* [Chromium](https://chromium.googlesource.com/chromium/src/)
---
### 鸣谢 Jetbrains
......@@ -149,7 +153,7 @@ func main() {
</p>
感谢您给项目点个Star
如果你觉得此项目对你有帮助,请点亮 Star
---
......
......@@ -21,7 +21,7 @@ import (
. "github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/types"
"github.com/energye/golcl/lcl/api"
"path"
"path/filepath"
"strings"
"unsafe"
)
......@@ -80,9 +80,10 @@ func (m *TCEFApplication) initDefaultSettings() {
} else {
panic("Unsupported system, currently only supports Windows, Mac OS, and Linux")
}
if m.FrameworkDirPath() == "" {
lp := common.LibPath()
// 默认CEF框架目录
// 当前执行文件所在目录或ENERGY_HOME环境配置目录
lp := common.FrameworkDir()
if lp != "" {
m.SetFrameworkDirPath(lp)
}
......@@ -151,10 +152,11 @@ func (m *TCEFApplication) FrameworkDirPath() string {
}
func (m *TCEFApplication) SetFrameworkDirPath(value string) {
common.SetFrameworkEnv(value)
imports.Proc(def.CEFAppConfig_SetFrameworkDirPath).Call(api.PascalStr(value))
// 默认 resources 和 locals 在同一目录
// resources 和 locals 在同一目录
m.SetResourcesDirPath(value)
m.SetLocalesDirPath(path.Join(value, "locales"))
m.SetLocalesDirPath(filepath.Join(value, "locales"))
}
// MainBundlePath 仅用于macOS
......@@ -1067,11 +1069,6 @@ func (m *TCEFApplication) LibVersion() string {
return version.LibVersion()
}
// LibBuildVersion 返回 lib-lcl 构建版本
func (m *TCEFApplication) LibBuildVersion() string {
return version.LibBuildVersion()
}
func (m *TCEFApplication) LibCefPath() string {
r1, _, _ := imports.Proc(def.CEFAppConfig_LibCefPath).Call()
return api.GoStr(r1)
......
......@@ -61,27 +61,25 @@ func Run(app *TCEFApplication) {
} else {
//externalMessagePump 和 multiThreadedMessageLoop 为 false 时, 启用 VF (ViewsFrameworkBrowserWindow) 窗口组件
if app.IsMessageLoop() {
// 启用VF窗口组件
BrowserWindow.appContextInitialized(app)
// 启用VFMessageLoop
// 初始化窗口组件
appContextInitialized(app)
}
if common.IsLinux() {
// linux gtk
lclwidget.CustomWidgetSetInitialization()
lcl.Application.Initialize()
}
// 启动主进程
success := app.StartMainProcess()
if success {
if app.IsUIGtk2() {
//LCL -> Linux GTK2 必须在主进程启动之后初始化组件
lclwidget.CustomWidgetSetInitialization()
}
// 主进程启动成功之后回调
if browserProcessStartAfterCallback != nil {
browserProcessStartAfterCallback(success)
}
appMainRunCallback()
if app.IsMessageLoop() {
if app.IsUIGtk2() {
//LCL -> Linux GTK2
lcl.Application.Initialize()
}
// VF窗口
// VF窗口 MessageLoop
app.RunMessageLoop()
} else {
// 创建LCL窗口组件
......
......@@ -51,6 +51,9 @@ func NewApplication(disableRegisDefaultEvent ...bool) *TCEFApplication {
return application
}
// CreateApplication
// 创建CEF Application
// 初始化CEF时必须创建,多进程模式每个application配置都应该相同
func CreateApplication() *TCEFApplication {
var result uintptr
imports.Proc(def.CEFApplication_Create).Call(uintptr(unsafe.Pointer(&result)))
......@@ -98,6 +101,11 @@ func (m *TCEFApplication) StartSubProcess() (result bool) {
return false
}
// DoMessageLoopWork
func (m *TCEFApplication) DoMessageLoopWork() {
imports.Proc(def.CEFApplication_DoMessageLoopWork).Call()
}
// RunMessageLoop
func (m *TCEFApplication) RunMessageLoop() {
defer func() {
......@@ -129,10 +137,14 @@ func (m *TCEFApplication) Free() {
}
}
// AddCustomCommandLine
// 添加自定义进程启动时添加的命令行参数
func (m *TCEFApplication) AddCustomCommandLine(commandLine, value string) {
imports.Proc(def.AddCustomCommandLine).Call(api.PascalStr(commandLine), api.PascalStr(value))
}
// SetOnRegCustomSchemes
// 自定义协议注册回调函数
func (m *TCEFApplication) SetOnRegCustomSchemes(fn GlobalCEFAppEventOnRegCustomSchemes) {
m.onRegCustomSchemes = fn
}
......@@ -150,32 +162,44 @@ func (m *TCEFApplication) defaultSetOnRegCustomSchemes() {
})
}
// TODO TCefPreferenceRegistrarRef
// SetOnRegisterCustomPreferences
// TODO 该函数还未完全实现
func (m *TCEFApplication) SetOnRegisterCustomPreferences(fn GlobalCEFAppEventOnRegisterCustomPreferences) {
imports.Proc(def.CEFGlobalApp_SetOnRegisterCustomPreferences).Call(api.MakeEventDataPtr(fn))
}
// SetOnContextInitialized
// 上下文初始化
func (m *TCEFApplication) SetOnContextInitialized(fn GlobalCEFAppEventOnContextInitialized) {
imports.Proc(def.CEFGlobalApp_SetOnContextInitialized).Call(api.MakeEventDataPtr(fn))
}
// 启动子进程之前自定义命令行参数设置
// SetOnBeforeChildProcessLaunch
// 启动子进程之前自定义命令行参数设置
func (m *TCEFApplication) SetOnBeforeChildProcessLaunch(fn GlobalCEFAppEventOnBeforeChildProcessLaunch) {
imports.Proc(def.CEFGlobalApp_SetOnBeforeChildProcessLaunch).Call(api.MakeEventDataPtr(fn))
}
// SetOnGetDefaultClient
// 获取并返回CefClient, 我们自己创建并返回到 *ICefClient = myCefClient
func (m *TCEFApplication) SetOnGetDefaultClient(fn GlobalCEFAppEventOnGetDefaultClient) {
imports.Proc(def.CEFGlobalApp_SetOnGetDefaultClient).Call(api.MakeEventDataPtr(fn))
}
// SetOnGetLocalizedString
// 获取并返回本地化
func (m *TCEFApplication) SetOnGetLocalizedString(fn GlobalCEFAppEventOnGetLocalizedString) {
imports.Proc(def.CEFGlobalApp_SetOnGetLocalizedString).Call(api.MakeEventDataPtr(fn))
}
// SetOnGetDataResource
// 获取并返回本地资源
func (m *TCEFApplication) SetOnGetDataResource(fn GlobalCEFAppEventOnGetDataResource) {
imports.Proc(def.CEFGlobalApp_SetOnGetDataResource).Call(api.MakeEventDataPtr(fn))
}
// SetOnGetDataResourceForScale
// 获取并返回本地资源大小
func (m *TCEFApplication) SetOnGetDataResourceForScale(fn GlobalCEFAppEventOnGetDataResourceForScale) {
imports.Proc(def.CEFGlobalApp_SetOnGetDataResourceForScale).Call(api.MakeEventDataPtr(fn))
}
......@@ -238,7 +262,8 @@ func (m *TCEFApplication) SetOnFocusedNodeChanged(fn GlobalCEFAppEventOnFocusedN
imports.Proc(def.CEFGlobalApp_SetOnFocusedNodeChanged).Call(api.MakeEventDataPtr(fn))
}
// 进程间通信处理消息接收
// SetOnProcessMessageReceived
// 进程间通信处理消息接收回调函数
func (m *TCEFApplication) SetOnProcessMessageReceived(fn RenderProcessMessageReceived) {
m.onProcessMessageReceived = fn
}
......
......@@ -36,19 +36,19 @@ type BrowserEvent struct {
onBeforePopup chromiumEventOnBeforePopupEx //default
onDragEnter chromiumEventOnDragEnterEx //default
onDraggableRegionsChanged chromiumEventOnDraggableRegionsChangedEx //default
onLoadEnd chromiumEventOnLoadEnd //default
onLoadEnd chromiumEventOnLoadEndEx //default
onAfterCreated chromiumEventOnAfterCreatedEx //default
onBeforeBrowser chromiumEventOnBeforeBrowserEx //default
onBeforeClose chromiumEventOnBeforeCloseEx //default
onClose chromiumEventOnCloseEx //default
onMainFrameChanged chromiumEventOnMainFrameChangedEx //default
onBeforeDownload chromiumEventOnBeforeDownload //default can cover
onBeforeDownload chromiumEventOnBeforeDownloadEx //default can cover
onKeyEvent chromiumEventOnKeyEventEx //default can cover
onProcessMessageReceived BrowseProcessMessageReceived //default
onProcessMessageReceived BrowseProcessMessageReceivedEx //default
onTitleChange chromiumEventOnTitleChangeEx //default
onContextMenuCommand chromiumEventOnContextMenuCommand //default can cover
onContextMenuCommand chromiumEventOnContextMenuCommandEx //default can cover
onBeforeContextMenu chromiumEventOnBeforeContextMenuEx //default can cover
onBeforeResourceLoad chromiumEventOnBeforeResourceLoad //default
onBeforeResourceLoad chromiumEventOnBeforeResourceLoadEx //default
onRenderCompMsg chromiumEventOnCompMsg //default windows
onGetResourceHandler chromiumEventOnGetResourceHandlerEx //default
}
......@@ -240,14 +240,14 @@ func (m *BrowserEvent) SetOnLoadError(event chromiumEventOnLoadError) {
}
// SetOnLoadEnd
func (m *BrowserEvent) SetOnLoadEnd(event chromiumEventOnLoadEnd) {
func (m *BrowserEvent) SetOnLoadEnd(event chromiumEventOnLoadEndEx) {
if Args.IsMain() {
m.onLoadEnd = event
}
}
// SetOnBeforeDownload
func (m *BrowserEvent) SetOnBeforeDownload(event chromiumEventOnBeforeDownload) {
func (m *BrowserEvent) SetOnBeforeDownload(event chromiumEventOnBeforeDownloadEx) {
if Args.IsMain() {
m.onBeforeDownload = event
}
......@@ -297,7 +297,7 @@ func (m *BrowserEvent) SetOnGetResourceHandler(event chromiumEventOnGetResourceH
m.onGetResourceHandler = event
} else {
m.ChromiumEvent().SetOnGetResourceHandler(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest) (resourceHandler *ICefResourceHandler) {
resourceHandler, _ = event(sender, browser, frame, request)
resourceHandler, _ = event(sender, browser, frame, request, nil)
return
})
}
......@@ -344,14 +344,14 @@ func (m *BrowserEvent) SetOnScrollOffsetChanged(event chromiumEventOnScrollOffse
}
// SetOnBrowseProcessMessageReceived
func (m *BrowserEvent) SetOnBrowseProcessMessageReceived(event BrowseProcessMessageReceived) {
func (m *BrowserEvent) SetOnBrowseProcessMessageReceived(event BrowseProcessMessageReceivedEx) {
if Args.IsMain() {
m.onProcessMessageReceived = event
}
}
// SetOnBeforeResourceLoad
func (m *BrowserEvent) SetOnBeforeResourceLoad(event chromiumEventOnBeforeResourceLoad) {
func (m *BrowserEvent) SetOnBeforeResourceLoad(event chromiumEventOnBeforeResourceLoadEx) {
if Args.IsMain() {
m.onBeforeResourceLoad = event
}
......@@ -421,7 +421,7 @@ func (m *BrowserEvent) SetOnBeforeContextMenu(event chromiumEventOnBeforeContext
}
// SetOnContextMenuCommand
func (m *BrowserEvent) SetOnContextMenuCommand(event chromiumEventOnContextMenuCommand) {
func (m *BrowserEvent) SetOnContextMenuCommand(event chromiumEventOnContextMenuCommandEx) {
if Args.IsMain() {
m.onContextMenuCommand = event
}
......
......@@ -14,6 +14,7 @@ package cef
import (
"fmt"
"github.com/energye/energy/v2/cef/internal/assets"
"github.com/energye/energy/v2/cef/internal/def"
"github.com/energye/energy/v2/cef/internal/window"
. "github.com/energye/energy/v2/common"
......@@ -116,9 +117,10 @@ func (m *LCLBrowserWindow) setProperty() {
// 默认
// vf png
// lcl ico
lcl.Application.Icon().LoadFromBytes(defaultICONIco)
if iconData := assets.DefaultICOICON(); iconData != nil {
lcl.Application.Icon().LoadFromBytes(iconData)
}
}
freeDefaultICON()
if wp.EnableCenterWindow {
m.SetSize(wp.Width, wp.Height)
m.SetCenterWindow(true)
......@@ -558,7 +560,7 @@ func (m *LCLBrowserWindow) defaultWindowCloseEvent() {
m.TForm.SetOnCloseQuery(m.closeQuery)
}
// EnableDefaultCloseEvent 启用默认关闭事件行为-该窗口将被关闭
// EnableDefaultCloseEvent 启用默认关闭事件
func (m *LCLBrowserWindow) EnableDefaultCloseEvent() {
m.defaultWindowCloseEvent()
m.registerDefaultChromiumCloseEvent()
......@@ -566,8 +568,12 @@ func (m *LCLBrowserWindow) EnableDefaultCloseEvent() {
// EnableAllDefaultEvent 启用所有默认事件行为
func (m *LCLBrowserWindow) EnableAllDefaultEvent() {
// 窗口关闭事件,window和chromium将以正确的行为关闭
m.defaultWindowCloseEvent()
// chromium事件,在回调事件中实现框架的默认行为
m.defaultChromiumEvent()
// 仅windows有的事件,窗口消息事件
m.registerWindowsCompMsgEvent()
}
// SetOnResize 事件,不会覆盖默认事件,返回值:false继续执行默认事件, true跳过默认事件
......@@ -821,7 +827,7 @@ func (m *LCLBrowserWindow) registerDefaultEvent() {
defaultAcceleratorCustom()
m.Chromium().SetOnProcessMessageReceived(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) bool {
if bwEvent.onProcessMessageReceived != nil {
return bwEvent.onProcessMessageReceived(sender, browser, frame, sourceProcess, message)
return bwEvent.onProcessMessageReceived(sender, browser, frame, sourceProcess, message, m)
}
return false
})
......@@ -830,38 +836,41 @@ func (m *LCLBrowserWindow) registerDefaultEvent() {
request.SetHeaderByName(assetserve.AssetsServerHeaderKeyName, assetserve.AssetsServerHeaderKeyValue, true)
}
if bwEvent.onBeforeResourceLoad != nil {
bwEvent.onBeforeResourceLoad(sender, browser, frame, request, callback, result)
bwEvent.onBeforeResourceLoad(sender, browser, frame, request, callback, result, m)
}
})
//事件可以被覆盖
m.Chromium().SetOnBeforeDownload(func(sender lcl.IObject, browser *ICefBrowser, beforeDownloadItem *ICefDownloadItem, suggestedName string, callback *ICefBeforeDownloadCallback) {
if bwEvent.onBeforeDownload != nil {
bwEvent.onBeforeDownload(sender, browser, beforeDownloadItem, suggestedName, callback)
bwEvent.onBeforeDownload(sender, browser, beforeDownloadItem, suggestedName, callback, m)
} else {
callback.Cont(consts.ExePath+consts.Separator+suggestedName, true)
// 默认保存到当前执行文件所在目录
callback.Cont(consts.ExeDir+consts.Separator+suggestedName, true)
}
})
m.Chromium().SetOnBeforeContextMenu(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) {
var flag bool
if bwEvent.onBeforeContextMenu != nil {
flag = bwEvent.onBeforeContextMenu(sender, browser, frame, params, model)
flag = bwEvent.onBeforeContextMenu(sender, browser, frame, params, model, m)
}
if !flag {
chromiumOnBeforeContextMenu(m, browser, frame, params, model)
}
})
m.Chromium().SetOnContextMenuCommand(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32, result *bool) {
m.Chromium().SetOnContextMenuCommand(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32) bool {
var result bool
if bwEvent.onContextMenuCommand != nil {
bwEvent.onContextMenuCommand(sender, browser, frame, params, commandId, eventFlags, result)
result = bwEvent.onContextMenuCommand(sender, browser, frame, params, commandId, eventFlags, m)
}
if !*result {
chromiumOnContextMenuCommand(m, browser, frame, params, commandId, eventFlags, result)
if !result {
result = chromiumOnContextMenuCommand(m, browser, frame, params, commandId, eventFlags)
}
return result
})
m.Chromium().SetOnAfterCreated(func(sender lcl.IObject, browser *ICefBrowser) {
var flag bool
if bwEvent.onAfterCreated != nil {
flag = bwEvent.onAfterCreated(sender, browser)
flag = bwEvent.onAfterCreated(sender, browser, m)
}
if !flag {
chromiumOnAfterCreate(m, browser)
......@@ -910,7 +919,7 @@ func (m *LCLBrowserWindow) registerDefaultEvent() {
})
m.Chromium().SetOnLoadEnd(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, httpStatusCode int32) {
if bwEvent.onLoadEnd != nil {
bwEvent.onLoadEnd(sender, browser, frame, httpStatusCode)
bwEvent.onLoadEnd(sender, browser, frame, httpStatusCode, m)
}
})
if m.WindowProperty().EnableWebkitAppRegion {
......@@ -926,7 +935,7 @@ func (m *LCLBrowserWindow) registerDefaultEvent() {
m.Chromium().SetOnGetResourceHandler(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest) (resourceHandler *ICefResourceHandler) {
//var flag bool
if bwEvent.onGetResourceHandler != nil {
resourceHandler, _ = bwEvent.onGetResourceHandler(sender, browser, frame, request)
resourceHandler, _ = bwEvent.onGetResourceHandler(sender, browser, frame, request, m)
}
//if !flag {
// resourceHandler = localLoadRes.getResourceHandler(browser, frame, request)
......
......@@ -198,3 +198,24 @@ func (m *auxTools) SetDevTools(devToolsWindow *devToolsWindow) {
func (m *auxTools) DevTools() *devToolsWindow {
return m.devToolsWindow
}
// NewBrowserWindow
// 创建浏览器窗口
// 根据当前主窗口类型创建
// 窗口类型
// LCL: 是基于LCL组件库创建的窗口,相比VF有多更的原生小部件使用,更多的窗口操作
// VF : 是基于CEF ViewFramework 组件创建的窗口, 相比LCL无法使用系统原生小部件,较少的窗口操作
func NewBrowserWindow(config *TCefChromiumConfig, windowProperty WindowProperty, owner ...lcl.IComponent) IBrowserWindow {
// 获取当前应用的主窗口
main := BrowserWindow.MainWindow()
// 设置为弹出的子窗口
windowProperty.WindowType = consts.WT_POPUP_SUB_BROWSER
if main.IsLCL() {
// 创建LCL窗口
return NewLCLBrowserWindow(config, windowProperty, owner...)
} else if main.IsViewsFramework() {
// 创建VF窗口
return NewViewsFrameworkBrowserWindow(config, windowProperty, owner...)
}
return nil
}
......@@ -285,14 +285,13 @@ func chromiumOnBeforeContextMenu(window IBrowserWindow, browser *ICefBrowser, fr
}
// chromiumOnContextMenuCommand 右键菜单 - 默认实现
func chromiumOnContextMenuCommand(window IBrowserWindow, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32, result *bool) {
func chromiumOnContextMenuCommand(window IBrowserWindow, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32) bool {
browserId := browser.Identifier()
defer func() {
if err := recover(); err != nil {
logger.Error("OnContextMenuCommand Error:", err, "browserId:", browserId)
}
}()
*result = true
if commandId == backId {
browser.GoBack()
} else if commandId == forwardId {
......@@ -322,7 +321,7 @@ func chromiumOnContextMenuCommand(window IBrowserWindow, browser *ICefBrowser, f
} else if commandId == imageSaveId {
browser.StartDownload(params.SourceUrl())
}
*result = true
return true
}
// chromiumOnBeforePopup 弹出窗口
......
......@@ -685,7 +685,7 @@ func init() {
eventFlags := uint32(getVal(5))
result := (*bool)(getPtr(6))
if !KeyAccelerator.commandIdEventCallback(browse, commandId, params, eventFlags, result) {
fn.(chromiumEventOnContextMenuCommand)(lcl.AsObject(sender), browse, frame, params, commandId, eventFlags, result)
*result = fn.(chromiumEventOnContextMenuCommand)(lcl.AsObject(sender), browse, frame, params, commandId, eventFlags)
}
params.Free()
case chromiumEventOnContextMenuDismissed:
......
......@@ -80,7 +80,7 @@ type IChromiumProc interface {
//SendProcessMessage(targetProcess CefProcessId, processMessage *ICefProcessMessage)
CefClient() *ICefClient
SendProcessMessageForJSONBytes(name string, targetProcess CefProcessId, message argument.IList)
CreateClientHandler(client *ICefClient, alsOSR bool) bool
CreateClientHandler(alsOSR bool) (*ICefClient, bool)
SetFocus(value bool)
SendExternalBeginFrame()
SendKeyEvent(event *TCefKeyEvent)
......@@ -603,11 +603,16 @@ func (m *TCEFChromium) ExecuteDevToolsMethod(messageId int32, method string, dic
_CEFChromium_ExecuteDevToolsMethod(m.Instance(), messageId, method, dictionaryValue)
}
func (m *TCEFChromium) CreateClientHandler(client *ICefClient, alsOSR bool) bool {
func (m *TCEFChromium) CreateClientHandler(alsOSR bool) (*ICefClient, bool) {
if !m.IsValid() {
return false
return nil, false
}
var result uintptr
ok := api.GoBool(_CEFChromium_CreateClientHandler(m.Instance(), uintptr(unsafe.Pointer(&result)), api.PascalBool(alsOSR)))
if result != 0 && ok {
return &ICefClient{instance: unsafe.Pointer(result), ct: CtOther}, ok
}
return api.GoBool(_CEFChromium_CreateClientHandler(m.Instance(), client.Instance(), api.PascalBool(alsOSR)))
return nil, false
}
func (m *TCEFChromium) SetFocus(value bool) {
......
......@@ -14,21 +14,9 @@ package cef
import (
"github.com/energye/energy/v2/cef/internal/def"
"github.com/energye/energy/v2/cef/internal/version"
"github.com/energye/energy/v2/common/imports"
"github.com/energye/golcl/lcl/api"
)
// defInit
// GlobalInit
func defInit() {
{
// Set pascal lib-lcl build version
r1, _, _ := imports.Proc(def.LibBuildVersion).Call()
version.SetLibBuildVersion(api.GoStr(r1))
}
}
// setMacOSXCommandLine
// 针对 MacOSX 设置命令行参数
//
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
......@@ -65,7 +65,7 @@ type chromiumEventOnFileDialog func(sender lcl.IObject, browser *ICefBrowser, mo
type chromiumEventOnGetAccessibilityHandler func(sender lcl.IObject, accessibilityHandler *ICefAccessibilityHandler)
type chromiumEventOnGetAudioParameters func(sender lcl.IObject, browser *ICefBrowser, params *TCefAudioParameters) bool
type chromiumEventOnGetResourceHandler func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest) (resourceHandler *ICefResourceHandler)
type chromiumEventOnGetResourceHandlerEx func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest) (resourceHandler *ICefResourceHandler, result bool)
type chromiumEventOnGetResourceHandlerEx func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, window IBrowserWindow) (resourceHandler *ICefResourceHandler, result bool)
type chromiumEventOnGetResourceRequestHandlerReqCtxHdlr func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, isNavigation, isDownload bool, requestInitiator string) (disableDefaultHandling bool, resourceRequestHandler *ICefResourceRequestHandler)
type chromiumEventOnGetResourceRequestHandlerReqHdlr func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, isNavigation, isDownload bool, requestInitiator string) (disableDefaultHandling bool, resourceRequestHandler *ICefResourceRequestHandler)
type chromiumEventOnGetResourceResponseFilter func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, response *ICefResponse) (responseFilter *ICefResponseFilter)
......@@ -123,7 +123,7 @@ type chromiumEventOnTitleChangeEx func(sender lcl.IObject, browser *ICefBrowser,
type chromiumEventOnRenderProcessTerminated func(sender lcl.IObject, browser *ICefBrowser, status consts.TCefTerminationStatus)
type chromiumEventOnCompMsg func(sender lcl.IObject, message *types.TMessage, lResult *types.LRESULT, aHandled *bool)
type chromiumEventOnAfterCreated func(sender lcl.IObject, browser *ICefBrowser)
type chromiumEventOnAfterCreatedEx func(sender lcl.IObject, browser *ICefBrowser) bool
type chromiumEventOnAfterCreatedEx func(sender lcl.IObject, browser *ICefBrowser, window IBrowserWindow) bool
type chromiumEventOnBeforeClose func(sender lcl.IObject, browser *ICefBrowser)
type chromiumEventOnBeforeCloseEx func(sender lcl.IObject, browser *ICefBrowser, window IBrowserWindow) bool
type chromiumEventOnClose func(sender lcl.IObject, browser *ICefBrowser, aAction *consts.TCefCloseBrowserAction)
......@@ -134,21 +134,25 @@ type chromiumEventOnLoadingStateChange func(sender lcl.IObject, browser *ICefBro
type chromiumEventOnLoadingProgressChange func(sender lcl.IObject, browser *ICefBrowser, progress float64)
type chromiumEventOnLoadError func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, errorCode consts.CEF_NET_ERROR, errorText, failedUrl string)
type chromiumEventOnLoadEnd func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, httpStatusCode int32)
type chromiumEventOnLoadEndEx func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, httpStatusCode int32, window IBrowserWindow)
type chromiumEventOnCookieSet func(sender lcl.IObject, success bool, ID int32)
type chromiumEventOnCookiesDeleted func(sender lcl.IObject, numDeleted int32)
type chromiumEventOnCookiesFlushed func(sender lcl.IObject)
type chromiumEventOnCookiesVisited func(sender lcl.IObject, cookie *ICefCookie)
type chromiumEventOnCookieVisitorDestroyed func(sender lcl.IObject, ID int32)
type chromiumEventOnBeforeContextMenu func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel)
type chromiumEventOnBeforeContextMenuEx func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) bool
type chromiumEventOnContextMenuCommand func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32, result *bool)
type chromiumEventOnBeforeContextMenuEx func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel, window IBrowserWindow) bool
type chromiumEventOnContextMenuCommand func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32) bool
type chromiumEventOnContextMenuCommandEx func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32, window IBrowserWindow) bool
type chromiumEventOnContextMenuDismissed func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame)
type chromiumEventOnFullScreenModeChange func(sender lcl.IObject, browser *ICefBrowser, fullscreen bool)
type chromiumEventOnBeforeDownload func(sender lcl.IObject, browser *ICefBrowser, downloadItem *ICefDownloadItem, suggestedName string, callback *ICefBeforeDownloadCallback)
type chromiumEventOnBeforeDownloadEx func(sender lcl.IObject, browser *ICefBrowser, downloadItem *ICefDownloadItem, suggestedName string, callback *ICefBeforeDownloadCallback, window IBrowserWindow)
type chromiumEventOnDownloadUpdated func(sender lcl.IObject, browser *ICefBrowser, downloadItem *ICefDownloadItem, callback *ICefDownloadItemCallback)
type chromiumEventOnKeyEvent func(sender lcl.IObject, browser *ICefBrowser, event *TCefKeyEvent, osEvent *consts.TCefEventHandle, result *bool)
type chromiumEventOnKeyEventEx func(sender lcl.IObject, browser *ICefBrowser, event *TCefKeyEvent, osEvent *consts.TCefEventHandle, window IBrowserWindow, result *bool)
type chromiumEventOnBeforeResourceLoad func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, callback *ICefCallback, result *consts.TCefReturnValue)
type chromiumEventOnBeforeResourceLoadEx func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, callback *ICefCallback, result *consts.TCefReturnValue, window IBrowserWindow)
type chromiumEventOnResourceResponse func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, response *ICefResponse, result *bool)
type chromiumEventOnResourceRedirect func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, response *ICefResponse, newUrl *string)
type chromiumEventOnResourceLoadComplete func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, response *ICefResponse, status consts.TCefUrlRequestStatus, receivedContentLength int64)
......@@ -170,6 +174,7 @@ type chromiumEventOnGetAuthCredentials func(sender lcl.IObject, browser *ICefBro
/************* ProcessMessageReceived *************/
type BrowseProcessMessageReceived func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) bool
type BrowseProcessMessageReceivedEx func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage, window IBrowserWindow) bool
type RenderProcessMessageReceived func(browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) bool
/************* TCEFApplication *************/
......@@ -214,6 +219,7 @@ type WindowComponentOnCanResize func(sender lcl.IObject, window *ICefWindow, aRe
type WindowComponentOnCanMaximize func(sender lcl.IObject, window *ICefWindow, aResult *bool)
type WindowComponentOnCanMinimize func(sender lcl.IObject, window *ICefWindow, aResult *bool)
type WindowComponentOnCanClose func(sender lcl.IObject, window *ICefWindow, aResult *bool)
type WindowComponentOnCanCloseEx func(sender lcl.IObject, cefWindow *ICefWindow, window IBrowserWindow, canClose *bool) bool
type WindowComponentOnAccelerator func(sender lcl.IObject, window *ICefWindow, commandId int32, aResult *bool)
type WindowComponentOnKeyEvent func(sender lcl.IObject, window *ICefWindow, event *TCefKeyEvent, aResult *bool)
......
......@@ -77,8 +77,6 @@ func GlobalInit(libs *embed.FS, resources *embed.FS) {
}
// go lcl
inits.Init(libs, resources)
// def
defInit()
// macos command line
setMacOSXCommandLine(api.PascalStr(Args.CommandLine()))
// main thread run call
......
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// Package assets energy internal assets
package assets
import "embed"
//go:embed assets
var assets embed.FS
// DefaultPNGICON energy app default icon.png
func DefaultPNGICON() []byte {
if d, err := assets.ReadFile("assets/icon.png"); err == nil {
return d
}
return nil
}
// DefaultICOICON energy app default icon.ico
func DefaultICOICON() []byte {
if d, err := assets.ReadFile("assets/icon.ico"); err == nil {
return d
}
return nil
}
### The bind package is currently not in use
\ No newline at end of file
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// V8 JSValue JSArray 类型实现
package bind
import (
"reflect"
"strconv"
)
type JSArray interface {
JSValue
AsArray() JSArray
Items() []JSValue
Get(index int) JSValue
fieldToBind()
Add(value any) JSValue
Set(index int, value any) JSValue
Clear()
Remove(index int)
}
// JSArray 类型 先保留 未添加
type jsArray struct {
V8Value
items []JSValue
}
func (m *jsArray) AsArray() JSArray {
if m.IsArray() {
return m
}
return nil
}
func (m *jsArray) Items() []JSValue {
return m.items
}
func (m *jsArray) Get(index int) JSValue {
if index >= 0 && index < len(m.items) {
return m.items[index]
}
return nil
}
func (m *jsArray) fieldToBind() {
for _, item := range m.Items() {
if item.IsObject() {
item.(JSObject).fieldToBind()
}
}
}
func (m *jsArray) Add(value any) JSValue {
item := m.createItem(len(m.items), value)
m.items = append(m.items, item)
if item.IsObject() {
item.(JSObject).fieldToBind()
} else if item.IsArray() {
array := item.(JSArray)
arrayRv := reflect.ValueOf(value)
for i := 0; i < arrayRv.Len(); i++ {
rv := arrayRv.Index(i)
array.Add(rv)
}
}
return item
}
func (m *jsArray) Set(index int, value any) JSValue {
if index >= 0 && index < len(m.items) {
if value == nil {
m.items[index] = nil
} else {
m.items[index] = m.createItem(index, value)
}
return m.items[index]
}
return nil
}
func (m *jsArray) Clear() {
for _, v := range m.items {
v.free()
}
m.items = make([]JSValue, 0, 0)
}
func (m *jsArray) Remove(index int) {
if v := m.Get(index); v != nil {
v.free()
m.items = append(m.items[:index], m.items[index+1:]...)
}
}
func (m *jsArray) createItem(index int, value any) JSValue {
var rv reflect.Value
switch value.(type) {
case reflect.Value:
rv = value.(reflect.Value)
default:
rv = reflect.ValueOf(value)
}
return m.createJSValue(strconv.Itoa(index), &rv)
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// Package bind Energy has not been exported or added yet
package bind
import (
"container/list"
"github.com/energye/energy/v2/cef/process"
"reflect"
"sync"
"unsafe"
)
var (
isMainProcess bool
isSubProcess bool
bind = &V8bind{hasFieldCollection: make(map[string]uintptr), fieldCollection: list.New()}
)
func init() {
isMainProcess = process.Args.IsMain()
isSubProcess = process.Args.IsRender()
}
// V8bind
type V8bind struct {
hasFieldCollection map[string]uintptr
fieldCollection *list.List
setLock, removeLock sync.Mutex
}
type Data struct {
P string `json:"P"`
T reflect.Kind `json:"T"`
V any `json:"V"`
}
func (m *V8bind) HasSize() int {
return len(m.hasFieldCollection)
}
func (m *V8bind) Size() int {
return m.fieldCollection.Len()
}
func (m *V8bind) HasFieldCollection() map[string]uintptr {
return m.hasFieldCollection
}
func (m *V8bind) FieldCollection() *list.List {
return m.fieldCollection
}
// Set 添加或修改
//
// 参数
// name: 唯一字段名, 重复将被覆盖
// value: 值
func (m *V8bind) Set(value JSValue) {
m.setLock.Lock()
defer m.setLock.Unlock()
// create set new value and return new id
if value.Id() == 0 {
value.setId(m.Add(value))
}
//if id, ok := m.hasFieldCollection[value.Name()]; ok {
// if value.Id() != id {
// // remove old id
// old := m.Remove(id)
// // gen add value and return new id
// value.setId(m.Add(value))
// // update name id
// m.hasFieldCollection[value.Name()] = value.Id()
// switch old.(type) {
// case JSValue:
// // old value set new id
// old.(JSValue).setId(value.Id())
// }
// }
//} else {
// // create set new value and return new id
// value.setId(m.Add(value))
// m.hasFieldCollection[value.Name()] = value.Id()
//}
}
// GetJSValue 返回 JSValue
func (m *V8bind) GetJSValue(id uintptr) JSValue {
if v := m.Get(id); v != nil {
return v.Value.(JSValue)
}
return nil
}
func (m *V8bind) ElementToJSValue(item *list.Element) JSValue {
if item != nil {
r, ok := item.Value.(JSValue)
if ok {
return r
}
}
return nil
}
// Add 添加 JSValue 并返回 id
func (m *V8bind) Add(value JSValue) uintptr {
return uintptr(unsafe.Pointer(m.fieldCollection.PushBack(value)))
}
// Get list element
func (m *V8bind) Get(id uintptr) *list.Element {
if id <= 0xFF {
return nil
}
return (*list.Element)(unsafe.Pointer(id))
}
// Remove 删除
func (m *V8bind) Remove(id uintptr) any {
m.removeLock.Lock()
defer m.removeLock.Unlock()
if v := m.Get(id); v != nil {
r := m.fieldCollection.Remove(v)
v.Value = nil
return r
}
return nil
}
// GetBinds 获取绑定的字段
func GetBinds(fn func(bind *V8bind)) {
fn(bind)
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// V8 JSValue JSFunction 类型实现
package bind
import (
"github.com/energye/energy/v2/pkgs/json"
jsoniter "github.com/json-iterator/go"
"reflect"
)
type JSFunction interface {
JSValue
AsFunction() JSFunction
// Invoke 调用函数
// 入参: 以参数列表形式传入参数
// 入参如果参数类型或数量不匹配这些参数将以类型的默认值传入
// nil 无入参
// 出参: 以参数列表形式返回参数
// 无返回值返回nil
Invoke(argumentList json.JSONArray) (resultArgument json.JSONArray)
}
type jsFunction struct {
V8Value
rv *reflect.Value
}
func (m *jsFunction) AsFunction() JSFunction {
if m.IsFunction() {
return m
}
return nil
}
func (m *jsFunction) Invoke(argumentList json.JSONArray) (resultArgument json.JSONArray) {
resultArgument = nil
if m.IsFunction() {
var (
argsSize int
inArgsValues []reflect.Value
)
if argumentList != nil {
argsSize = argumentList.Size()
}
rt := m.rv.Type()
inArgsCount := rt.NumIn()
inArgsValues = make([]reflect.Value, inArgsCount)
for i := 0; i < inArgsCount; i++ {
inType := rt.In(i)
if i < argsSize {
argsValue := argumentList.GetByIndex(i)
if argsValue != nil {
switch inType.Kind() {
case reflect.String:
inArgsValues[i] = reflect.ValueOf(argsValue.String())
case reflect.Int:
inArgsValues[i] = reflect.ValueOf(argsValue.Int())
case reflect.Int8:
inArgsValues[i] = reflect.ValueOf(int8(argsValue.Int()))
case reflect.Int16:
inArgsValues[i] = reflect.ValueOf(int16(argsValue.Int()))
case reflect.Int32:
inArgsValues[i] = reflect.ValueOf(int32(argsValue.Int()))
case reflect.Int64:
inArgsValues[i] = reflect.ValueOf(int64(argsValue.Int()))
case reflect.Uint:
inArgsValues[i] = reflect.ValueOf(uint(argsValue.Int()))
case reflect.Uint8:
inArgsValues[i] = reflect.ValueOf(uint8(argsValue.Int()))
case reflect.Uint16:
inArgsValues[i] = reflect.ValueOf(uint16(argsValue.Int()))
case reflect.Uint32:
inArgsValues[i] = reflect.ValueOf(uint32(argsValue.Int()))
case reflect.Uint64:
inArgsValues[i] = reflect.ValueOf(uint64(argsValue.Int()))
case reflect.Uintptr:
inArgsValues[i] = reflect.ValueOf(uintptr(argsValue.Int()))
case reflect.Float32:
inArgsValues[i] = reflect.ValueOf(float32(argsValue.Float()))
case reflect.Float64:
inArgsValues[i] = reflect.ValueOf(argsValue.Float())
case reflect.Bool:
inArgsValues[i] = reflect.ValueOf(argsValue.Bool())
case reflect.Struct:
if argsValue.IsObject() {
// struct
if jsonBytes := argsValue.Bytes(); jsonBytes != nil {
v := reflect.New(inType)
if err := jsoniter.Unmarshal(jsonBytes, v.Interface()); err == nil {
inArgsValues[i] = v.Elem()
}
}
}
case reflect.Map:
if argsValue.IsObject() {
// map key=string : value != interface
if inType.Elem().Kind() != reflect.Interface {
if jsonBytes := argsValue.Bytes(); jsonBytes != nil {
vv := reflect.New(inType)
if err := jsoniter.Unmarshal(jsonBytes, vv.Interface()); err == nil {
inArgsValues[i] = vv.Elem()
}
}
} else {
inArgsValues[i] = reflect.ValueOf(argsValue.Data())
}
}
case reflect.Slice:
if argsValue.IsArray() {
// slice value != interface
if inType.Elem().Kind() != reflect.Interface {
if jsonBytes := argsValue.Bytes(); jsonBytes != nil {
vv := reflect.New(inType)
if err := jsoniter.Unmarshal(jsonBytes, vv.Interface()); err == nil {
inArgsValues[i] = vv.Elem()
}
}
} else {
inArgsValues[i] = reflect.ValueOf(argsValue.Data())
}
}
}
}
}
if !inArgsValues[i].IsValid() {
inArgsValues[i] = reflect.New(inType).Elem()
}
}
// call
resultValues := m.rv.Call(inArgsValues)
if len(resultValues) > 0 {
// call result
resultArgument = json.NewJSONArray(nil)
for _, result := range resultValues {
res := result.Interface()
switch res.(type) {
case error:
resultArgument.Add(res.(error).Error())
default:
resultArgument.Add(res)
}
}
}
}
return
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// V8 JSValue JSObject 实现
package bind
import (
"reflect"
"unsafe"
)
type JSObject interface {
JSValue
ObjectValue() any
Get(fieldName string) JSValue
Set(fieldName string, value any)
fieldToBind()
}
type jsObject struct {
V8Value
}
func (m *jsObject) ObjectValue() any {
if m.IsObject() {
return m.JsonData.Data()
}
return nil
}
func (m *jsObject) Get(fieldName string) JSValue {
if fieldName == "" {
return nil
}
if m.IsObject() {
rv := m.Data().(*reflect.Value).Elem().FieldByName(fieldName)
return m.createJSValue(fieldName, &rv)
}
return nil
}
// fieldToBind 对象字段绑定
func (m *jsObject) fieldToBind() {
if m.IsObject() {
rv := *m.Data().(*reflect.Value)
rt := rv.Type()
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
rt = rt.Elem()
}
for i := 0; i < rv.NumField(); i++ {
field := rv.Field(i)
name := rt.Field(i).Name
value := m.createJSValue(name, &field)
if value.IsObject() {
value.(JSObject).fieldToBind()
} else if value.IsArray() {
for _, item := range value.(JSArray).Items() {
if item.IsObject() {
item.(JSObject).fieldToBind()
} else if item.IsArray() {
item.(JSArray).fieldToBind()
}
}
}
}
}
}
func (m *jsObject) Set(fieldName string, value any) {
if m.IsObject() {
field := m.Data().(*reflect.Value).Elem().FieldByName(fieldName)
switch field.Kind() {
case reflect.String:
if v, ok := value.(string); ok {
*(*string)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Int:
if v, ok := value.(int); ok {
*(*int)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Int8:
if v, ok := value.(int8); ok {
*(*int8)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Int16:
if v, ok := value.(int16); ok {
*(*int16)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Int32:
if v, ok := value.(int32); ok {
*(*int32)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Int64:
if v, ok := value.(int64); ok {
*(*int64)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Uint:
if v, ok := value.(uint); ok {
*(*uint)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Uint8:
if v, ok := value.(uint8); ok {
*(*uint8)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Uint16:
if v, ok := value.(uint16); ok {
*(*uint16)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Uint32:
if v, ok := value.(uint32); ok {
*(*uint32)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Uint64:
if v, ok := value.(uint64); ok {
*(*uint64)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Float32:
if v, ok := value.(float32); ok {
*(*float32)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Float64:
if v, ok := value.(float64); ok {
*(*float64)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Bool:
if v, ok := value.(bool); ok {
*(*bool)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Ptr: //指针仅支持 struct slice map
valRv := reflect.ValueOf(value)
fieldType := field.Type().Elem()
valRvKind := valRv.Kind()
if valRvKind == reflect.Ptr {
valRvKind = valRv.Elem().Kind()
}
if fieldType.Kind() == reflect.Struct && valRvKind == reflect.Struct {
field.Set(valRv)
} else if field.Kind() == reflect.Slice && valRvKind == reflect.Slice {
field.Set(valRv)
} else if field.Kind() == reflect.Map && valRvKind == reflect.Map {
field.Set(valRv)
}
case reflect.Struct:
valRv := reflect.ValueOf(value)
field.Set(valRv)
case reflect.Slice:
valRv := reflect.ValueOf(value)
field.Set(valRv)
case reflect.Map:
valRv := reflect.ValueOf(value)
field.Set(valRv)
}
}
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// V8 JSValue JSUndefined 实现
package bind
type JSUndefined interface {
JSValue
AsUndefined() JSUndefined
UndefinedValue() string
}
type jsUndefined struct {
V8Value
}
func (m *jsUndefined) AsUndefined() JSUndefined {
if m.IsUndefined() {
return m
}
return nil
}
func (m *jsUndefined) UndefinedValue() string {
return m.JsonData.String()
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// V8 JSValue 动态类型实现
//
// 动态类型是可变类型,对于JS语言可以动态赋任意类型的值
//
// 字段值仅主进程有效, 非主进程字段值为默认值
package bind
import (
"github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/pkgs/json"
"reflect"
"strconv"
"strings"
)
const (
null = "null"
undefined = "undefined"
)
// BindType 绑定值类型
// 动态类型是可变类型, NewDynamic创建绑定变量, 函数传值方式
// 静态类型是不可变类型, NewStatic创建绑定变量, 直接传入变量指针, 非 interface{} 类型
type BindType int8
const (
BtDynamic BindType = iota // 动态类型
BtStatic // 静态类型
)
// JSValue
//
// GO和JS动态变量类型
//
// 在主进程有效
type JSValue interface {
Name() string //当前变量绑定的名称
JSON() json.JSON //
Value() any //
SetValue(value any) //设置新值
IsInteger() bool //是否 Integer
IsDouble() bool //是否 Double
IsString() bool //是否 String
IsBoolean() bool //是否 Boolean
IsObject() bool //是否 Object
IsArray() bool //是否 Array
IsUndefined() bool //是否 Undefined
IsFunction() bool //是否 Function
AsInteger() JSInteger //转换为 Integer 失败返回 nil
AsDouble() JSDouble //转换为 Double 失败返回 nil
AsString() JSString //转换为 String 失败返回 nil
AsBoolean() JSBoolean //转换为 Boolean 失败返回 nil
AsUndefined() JSUndefined //转换为 Undefined 失败返回 nil
AsFunction() JSFunction //转换为 Function 失败返回 nil
//AsArray() JSArray
AsV8Value() JSValue //转换为 JSValue
StringValue() string
BooleanValue() bool
DoubleValue() float64
IntegerValue() int
UndefinedValue() string
// Invoke 调用函数
// 入参: 以参数列表形式传入参数
// 入参如果参数类型或数量不匹配这些参数将以类型的默认值传入
// nil 无入参
// 出参: 以参数列表形式返回参数
// 无返回值返回nil
Invoke(argumentList json.JSONArray) (resultArgument json.JSONArray)
Id() int //指针ID
Type() reflect.Kind //值类型
BindType() BindType //绑定类型
setId(id uintptr)
free()
}
// V8Value 绑定到JS的字段
type V8Value struct {
*json.JsonData
id uintptr
name string
bt BindType
}
//BindType 绑定类型
func (m *V8Value) BindType() BindType {
return m.bt
}
func (m *V8Value) free() {
bind.Remove(uintptr(m.Id()))
m.id = 0
m.name = ""
}
// nameKey
func (m *V8Value) nameKey(pName, name string) {
var concat = strings.Builder{}
concat.WriteString(pName)
concat.WriteString(".")
concat.WriteString(name)
m.name = concat.String()
}
// createJSValue 创建 JSValue
func (m *V8Value) createJSValue(name string, rv *reflect.Value) JSValue {
kind := rv.Kind()
if kind == reflect.Ptr {
kind = rv.Elem().Kind()
}
switch kind {
case reflect.String:
v := new(jsString)
v.nameKey(m.name, name)
v.JsonData = json.NewJsonData(reflect.String, rv.Len(), rv)
v.bt = m.bt
bind.Set(v)
return v
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v := new(jsInteger)
v.nameKey(m.name, name)
v.JsonData = json.NewJsonData(reflect.Int, strconv.IntSize, rv)
v.bt = m.bt
bind.Set(v)
return v
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v := new(jsInteger)
v.nameKey(m.name, name)
v.JsonData = json.NewJsonData(reflect.Uint, strconv.IntSize, rv)
v.bt = m.bt
bind.Set(v)
return v
case reflect.Float32, reflect.Float64:
v := new(jsDouble)
v.nameKey(m.name, name)
v.JsonData = json.NewJsonData(reflect.Float64, 8, rv)
v.bt = m.bt
bind.Set(v)
return v
case reflect.Bool:
v := new(jsBoolean)
v.nameKey(m.name, name)
v.JsonData = json.NewJsonData(reflect.Bool, 1, rv)
v.bt = m.bt
bind.Set(v)
return v
case reflect.Struct:
v := new(jsObject)
v.nameKey(m.name, name)
v.JsonData = json.NewJsonData(reflect.Map, 0, rv)
v.bt = m.bt
bind.Set(v)
return v
case reflect.Map:
v := new(jsObject)
v.nameKey(m.name, name)
v.JsonData = json.NewJsonData(reflect.Map, rv.Len(), rv)
v.bt = m.bt
bind.Set(v)
return v
case reflect.Slice:
v := new(jsArray)
v.nameKey(m.name, name)
v.JsonData = json.NewJsonData(reflect.Slice, rv.Len(), rv)
v.bt = m.bt
bind.Set(v)
return v
case reflect.Func:
v := new(jsFunction)
v.nameKey(m.name, name)
v.JsonData = json.NewJsonData(reflect.Func, 0, rv)
v.rv = rv
v.bt = m.bt
bind.Set(v)
return v
default:
v := new(jsUndefined)
v.nameKey(m.name, name)
v.JsonData = json.NewJsonData(consts.NIL, 0, null)
v.bt = m.bt
bind.Set(v)
return v
}
}
func (m *V8Value) JSON() json.JSON {
return m.JsonData
}
func (m *V8Value) Value() any {
if m.JsonData != nil {
return m.JsonData.Data()
}
return nil
}
// SetValue 设置值
func (m *V8Value) SetValue(value any) {
if isMainProcess {
if m.bt == BtDynamic {
m.JsonData.SetValue(value)
} else if m.bt == BtStatic {
if m.JsonData.Data() != nil {
rv := reflect.ValueOf(value)
kind := rv.Kind()
if kind == reflect.Ptr {
kind = rv.Elem().Kind()
}
m.JsonData.Data().(*reflect.Value).Set(rv)
}
}
}
}
func (m *V8Value) setId(id uintptr) {
m.id = id
}
func (m *V8Value) Id() int {
return int(m.id)
}
func (m *V8Value) Name() string {
return m.name
}
func (m *V8Value) IsString() bool {
return m.JsonData.IsString()
}
func (m *V8Value) IsInteger() bool {
return m.JsonData.IsInt() || m.JsonData.IsUInt()
}
func (m *V8Value) IsDouble() bool {
return m.JsonData.IsFloat()
}
func (m *V8Value) IsBoolean() bool {
return m.JsonData.IsBool()
}
func (m *V8Value) IsArray() bool {
return m.JsonData.IsArray()
}
func (m *V8Value) IsObject() bool {
return m.JsonData.IsObject()
}
func (m *V8Value) IsFunction() bool {
return m.JsonData.Type() == reflect.Func
}
func (m *V8Value) IsUndefined() bool {
return m.JsonData.Type() == consts.NIL
}
func (m *V8Value) AsString() JSString {
if m.IsString() {
return m
}
return nil // default
}
func (m *V8Value) StringValue() string {
return m.JsonData.String()
}
func (m *V8Value) AsInteger() JSInteger {
if m.IsInteger() {
return m
}
return nil // default
}
func (m *V8Value) IntegerValue() int {
return m.JsonData.Int()
}
func (m *V8Value) AsDouble() JSDouble {
if m.IsDouble() {
return m
}
return nil // default
}
func (m *V8Value) DoubleValue() float64 {
return m.JsonData.Float()
}
func (m *V8Value) AsBoolean() JSBoolean {
if m.IsBoolean() {
return m
}
return nil // default
}
func (m *V8Value) BooleanValue() bool {
return m.JsonData.Bool()
}
func (m *V8Value) AsUndefined() JSUndefined {
if m.IsUndefined() {
return m
}
return nil // default
}
func (m *V8Value) UndefinedValue() string {
return m.JsonData.String()
}
func (m *V8Value) AsFunction() JSFunction {
if m.IsFunction() {
return m
}
return nil // default
}
func (m *V8Value) Invoke(argumentList json.JSONArray) (resultArgument json.JSONArray) {
if f := m.AsFunction(); f != nil {
return f.Invoke(argumentList)
}
return nil
}
//func (m *V8Value) AsArray() JSArray {
// if m.IsArray() {
// v := new(jsArray)
// v.name = m.name
// v.value = m.value.JsonData()
// v.bt = m.bt
// return v
// }
// return nil // default
//}
func (m *V8Value) AsV8Value() JSValue {
return m
}
func (m *V8Value) Type() reflect.Kind {
if m == nil {
return reflect.Invalid
}
return m.JsonData.Type()
}
// NewInteger GO&JS 数字类型
func NewInteger(name string, value int) JSInteger {
if name == "" || (!isMainProcess && !isSubProcess) {
return nil
}
v := new(jsInteger)
v.name = name
v.JsonData = json.NewJsonData(reflect.Int, 4, value)
v.bt = BtDynamic
bind.Set(v)
return v
}
// NewString GO&JS 字符串类型
func NewString(name, value string) JSString {
if name == "" || (!isMainProcess && !isSubProcess) {
return nil
}
v := new(jsString)
v.name = name
v.JsonData = json.NewJsonData(reflect.String, len(value), value)
v.bt = BtDynamic
bind.Set(v)
return v
}
// NewDouble GO&JS 浮点类型
func NewDouble(name string, value float64) JSDouble {
if name == "" || (!isMainProcess && !isSubProcess) {
return nil
}
v := new(jsDouble)
v.name = name
v.JsonData = json.NewJsonData(reflect.Float64, 8, value)
v.bt = BtDynamic
bind.Set(v)
return v
}
// NewBoolean GO&JS 布尔类型
func NewBoolean(name string, value bool) JSBoolean {
if name == "" || (!isMainProcess && !isSubProcess) {
return nil
}
v := new(jsBoolean)
v.name = name
v.JsonData = json.NewJsonData(reflect.Bool, 1, value)
v.bt = BtDynamic
bind.Set(v)
return v
}
// NewUndefined GO&JS 未定义类型
func NewUndefined(name string) JSUndefined {
if name == "" || (!isMainProcess && !isSubProcess) {
return nil
}
v := new(jsUndefined)
v.name = name
v.JsonData = json.NewJsonData(consts.NIL, 0, undefined)
v.bt = BtDynamic
bind.Set(v)
return v
}
// NewFunction GO&JS 函数类型
func NewFunction(name string, fn any) JSFunction {
if name == "" || (!isMainProcess && !isSubProcess) {
return nil
}
rv := reflect.ValueOf(fn)
if rv.Kind() != reflect.Func {
return nil
}
v := new(jsFunction)
v.name = name
v.JsonData = json.NewJsonData(reflect.Func, 0, &rv)
v.rv = &rv
v.bt = BtStatic
bind.Set(v)
return v
}
// NewObject GO&JS 对象类型 &struct{} 仅结构
func NewObject(object any) JSObject {
if object == nil || (!isMainProcess && !isSubProcess) {
return nil
}
rv := reflect.ValueOf(object)
kind := rv.Kind()
//必须是指针
if kind != reflect.Ptr {
return nil
}
kind = rv.Elem().Kind()
//必须是结构
if kind != reflect.Struct {
return nil
}
v := new(jsObject)
v.name = rv.Type().Elem().Name()
v.JsonData = json.NewJsonData(reflect.Map, 0, &rv)
v.bt = BtStatic
bind.Set(v)
v.fieldToBind()
return v
}
// NewArray GO&JS 数组类型
func NewArray(name string, values []any) JSArray {
if name == "" || values == nil || (!isMainProcess && !isSubProcess) {
return nil
}
v := new(jsArray)
v.name = name
v.JsonData = json.NewJsonData(reflect.Slice, len(values), values)
v.bt = BtStatic
bind.Set(v)
for _, value := range values {
v.Add(value)
}
return v
}
......@@ -26,8 +26,6 @@ const (
// TForm
Form_SetOnMessagesEvent
// CEF
LibVersion
LibBuildVersion
CEF_Win_CreateRectRgn
CEF_Win_SetRectRgn
CEF_Win_DeleteObject
......@@ -260,6 +258,7 @@ const (
CEFWorkScheduler_SetDepleteWorkDelay
CEFWorkScheduler_SetUseQueueThread
// application
CEFApplication_DoMessageLoopWork
CEFApplication_RunMessageLoop
CEFApplication_QuitMessageLoop
CEFApplication_Create
......
......@@ -26,8 +26,6 @@ func init() {
// TForm
dllimports.NewEnergyImport("Form_SetOnMessagesEvent", 0),
//CEF
dllimports.NewEnergyImport("LibVersion", 0),
dllimports.NewEnergyImport("LibBuildVersion", 0),
dllimports.NewEnergyImport("CEF_Win_CreateRectRgn", 0),
dllimports.NewEnergyImport("CEF_Win_SetRectRgn", 0),
dllimports.NewEnergyImport("CEF_Win_DeleteObject", 0),
......@@ -260,6 +258,7 @@ func init() {
dllimports.NewEnergyImport("CEFWorkScheduler_SetDepleteWorkDelay", 0),
dllimports.NewEnergyImport("CEFWorkScheduler_SetUseQueueThread", 0),
//application
dllimports.NewEnergyImport("CEFApplication_DoMessageLoopWork", 0),
dllimports.NewEnergyImport("CEFApplication_RunMessageLoop", 0),
dllimports.NewEnergyImport("CEFApplication_QuitMessageLoop", 0),
dllimports.NewEnergyImport("CEFApplication_Create", 0),
......
......@@ -158,9 +158,9 @@ func EmitTarget(name string, tag target.ITarget, argument ...any) {
if name == "" {
return
}
if tag != nil && tag.TargetType() == target.TgGo {
if tag.ChannelId() > 0 {
emitSendToGoChannel(0, tag.ChannelId(), name, argument)
if tag != nil {
if (tag.ChannelId() > 0 && tag.TargetType() == target.TgGoSub) || (tag.TargetType() == target.TgGoMain) {
emitSendToGoChannel(0, tag, name, argument)
return
}
}
......@@ -177,10 +177,10 @@ func EmitTargetAndCallback(name string, tag target.ITarget, argument []any, fn a
return
}
var messageId int32 = 0
if tag != nil && tag.TargetType() == target.TgGo {
if tag.ChannelId() > 0 {
if tag != nil {
if (tag.ChannelId() > 0 && tag.TargetType() == target.TgGoSub) || (tag.TargetType() == target.TgGoMain) {
messageId = browser.addEmitCallback(fn)
emitSendToGoChannel(messageId, tag.ChannelId(), name, argument)
emitSendToGoChannel(messageId, tag, name, argument)
return
}
}
......
......@@ -12,11 +12,12 @@ package ipc
import (
"github.com/energye/energy/v2/cef/ipc/argument"
"github.com/energye/energy/v2/cef/ipc/target"
)
// emitSendToChannel
// trigger the specified target Go channel event
func emitSendToGoChannel(messageId int32, channelId int64, eventName string, arguments []any) {
func emitSendToGoChannel(messageId int32, tag target.ITarget, eventName string, arguments []any) {
message := &argument.List{
Id: messageId,
Name: InternalIPCGoExecuteGoEvent,
......@@ -24,10 +25,14 @@ func emitSendToGoChannel(messageId int32, channelId int64, eventName string, arg
Data: arguments,
}
if isMainProcess {
BrowserChan().IPC().Send(channelId, message.Bytes())
BrowserChan().IPC().Send(tag.ChannelId(), message.Bytes())
} else {
message.BId = RenderChan().BrowserId()
RenderChan().IPC().SendToChannel(channelId, message.Bytes())
if tag.TargetType() == target.TgGoSub {
RenderChan().IPC().SendToChannel(tag.ChannelId(), message.Bytes())
} else if tag.TargetType() == target.TgGoMain {
RenderChan().IPC().Send(message.Bytes())
}
}
message.Reset()
}
......@@ -13,26 +13,7 @@ package version
import "github.com/energye/liblclbinres"
// Current Branch Version
var (
libBuildVersion = "" // pascal lib-lcl build
)
// LibVersion return lib-lcl version
func LibVersion() string {
return liblclbinres.LibVersion()
}
// LibBuildVersion return pascal lib build version
func LibBuildVersion() string {
return libBuildVersion
}
// SetLibBuildVersion Set pascal lib build version
func SetLibBuildVersion(version string) {
if version == "" {
libBuildVersion = "0.0.0"
} else {
libBuildVersion = version
}
}
package argument
import (
"testing"
)
func TestList(t *testing.T) {
list := &List{
Data: make([]string, 0),
}
json := list.JSON()
json.Add("value1")
json.Add("value2")
json.Add("value3")
if json.Size() != 3 {
t.Fail()
}
if json.GetStringByIndex(1) != "value2" {
t.Fail()
}
data := json.Bytes()
if data == nil {
t.Fail()
}
}
......@@ -14,12 +14,14 @@ package target
// Type
// 0: Trigger the JS event of the specified target process
// 1: Trigger GO events for the specified target process
// 1: Trigger TgGoSub events for the specified target sub process
// 2: Trigger TgGoMain events for the specified target main process
type Type int8
const (
TgJs Type = iota //JS Event
TgGo //GO Event
TgJs Type = iota //JS Event
TgGoSub //GO Event sub
TgGoMain //GO Event main
)
// ITarget
......@@ -43,7 +45,7 @@ type Target struct {
// browserId: browser window ID
// channelId: IPC channelID, frameId or GO IPC channelID
// targetType: Optional parameter, target type default 0
// Type: TgJs:JS Event, TgGo:GO Event
// Type: TgJs:JS Event, TgGoSub:GO Sub Event, TgGoMain:GO Main Event
func NewTarget(browserId int32, channelId int64, targetType ...Type) ITarget {
m := &Target{
browseId: browserId,
......@@ -55,6 +57,14 @@ func NewTarget(browserId int32, channelId int64, targetType ...Type) ITarget {
return m
}
// NewTargetMain Create a new Emit target Main Process
// targetType: TgGoMain
func NewTargetMain() ITarget {
return &Target{
targetType: TgGoMain,
}
}
// TargetType
// target type
// 0: Trigger JS event
......
......@@ -105,7 +105,7 @@ func (m LocalLoadConfig) Build() *LocalLoadConfig {
} else if config.Home[0] != '/' {
config.Home = "/" + config.Home
}
m.exePath, _ = os.Getwd()
m.exePath = ExeDir
// 默认的资源目录
if config.ResRootDir == "" {
if config.FS != nil {
......@@ -133,7 +133,7 @@ func (m *LocalLoadResource) loadDefaultURL(window IBrowserWindow, browser *ICefB
if localLoadRes.enable() {
var homeURL string
if BrowserWindow.Config.Url != defaultAboutBlank {
homeURL = BrowserWindow.Config.Url
homeURL = window.WindowProperty().Url
} else {
defaultURL := new(bytes.Buffer)
defaultURL.WriteString(m.Scheme)
......
......@@ -2,7 +2,6 @@ package cef
import (
"bytes"
"github.com/energye/energy/v2/consts"
"log"
"net/http"
"testing"
......@@ -10,14 +9,7 @@ import (
func TestXHRProxyClientSSLSend(t *testing.T) {
proxy := &XHRProxy{
Scheme: consts.LpsHttps,
IP: "energy.yanghy.cn",
SSL: XHRProxySSL{
RootDir: "\\resources\\ssl",
Cert: "demo.energy.pem",
Key: "demo.energy.key",
CARoots: []string{"root.cer"},
},
IP: "energy.yanghy.cn",
}
proxy.init()
httpRequest, err := http.NewRequest("GET", "https://energy.yanghy.cn/api/energy/download", nil)
......
......@@ -65,10 +65,15 @@ func (m *ICefClient) Free() {
}
}
// IsSelfEvent
// 当前client对象是自己事件代理
func (m *ICefClient) IsSelfEvent() bool {
return m.ct == consts.CtSelfOwn
}
// IsOtherEvent
// 当前client对象是其他对象事件代理
// 例如chromium events
func (m *ICefClient) IsOtherEvent() bool {
return m.ct == consts.CtOther
}
......
......@@ -437,71 +437,71 @@ func (m *TCEFViewComponent) GetHeightForWidth(width int32) int32 {
}
func (m *TCEFViewComponent) SetOnGetPreferredSize(fn onGetPreferredSize) {
if !m.IsValid() {
return
}
//if !m.IsValid() {
// return
//}
imports.Proc(def.ViewComponent_SetOnGetPreferredSize).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
func (m *TCEFViewComponent) SetOnGetMinimumSize(fn onGetMinimumSize) {
if !m.IsValid() {
return
}
//if !m.IsValid() {
// return
//}
imports.Proc(def.ViewComponent_SetOnGetMinimumSize).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
func (m *TCEFViewComponent) SetOnGetMaximumSize(fn onGetMaximumSize) {
if !m.IsValid() {
return
}
//if !m.IsValid() {
// return
//}
imports.Proc(def.ViewComponent_SetOnGetMaximumSize).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
func (m *TCEFViewComponent) SetOnGetHeightForWidth(fn onGetHeightForWidth) {
if !m.IsValid() {
return
}
//if !m.IsValid() {
// return
//}
imports.Proc(def.ViewComponent_SetOnGetHeightForWidth).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
func (m *TCEFViewComponent) SetOnParentViewChanged(fn onParentViewChanged) {
if !m.IsValid() {
return
}
//if !m.IsValid() {
// return
//}
imports.Proc(def.ViewComponent_SetOnParentViewChanged).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
func (m *TCEFViewComponent) SetOnChildViewChanged(fn onChildViewChanged) {
if !m.IsValid() {
return
}
//if !m.IsValid() {
// return
//}
imports.Proc(def.ViewComponent_SetOnChildViewChanged).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
func (m *TCEFViewComponent) SetOnWindowChanged(fn onWindowChanged) {
if !m.IsValid() {
return
}
//if !m.IsValid() {
// return
//}
imports.Proc(def.ViewComponent_SetOnWindowChanged).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
func (m *TCEFViewComponent) SetOnLayoutChanged(fn onLayoutChanged) {
if !m.IsValid() {
return
}
//if !m.IsValid() {
// return
//}
imports.Proc(def.ViewComponent_SetOnLayoutChanged).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
func (m *TCEFViewComponent) SetOnFocus(fn onFocus) {
if !m.IsValid() {
return
}
//if !m.IsValid() {
// return
//}
imports.Proc(def.ViewComponent_SetOnFocus).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
func (m *TCEFViewComponent) SetOnBlur(fn onBlur) {
if !m.IsValid() {
return
}
//if !m.IsValid() {
// return
//}
imports.Proc(def.ViewComponent_SetOnBlur).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
......@@ -45,51 +45,81 @@ func (m *TCEFWindowComponent) CreateTopLevelWindow() {
// Show 显示窗口
func (m *TCEFWindowComponent) Show() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_Show).Call(m.Instance())
}
// Hide 显示窗口
func (m *TCEFWindowComponent) Hide() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_Hide).Call(m.Instance())
}
// CenterWindow 根据大小窗口居中
func (m *TCEFWindowComponent) CenterWindow(size *TCefSize) {
if !m.IsValid() || size == nil {
return
}
imports.Proc(def.CEFWindowComponent_CenterWindow).Call(m.Instance(), uintptr(unsafe.Pointer(size)))
}
// Close 关闭窗口, 主窗口调用
func (m *TCEFWindowComponent) Close() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_Close).Call(m.Instance())
}
// Activate 激活窗口
func (m *TCEFWindowComponent) Activate() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_Activate).Call(m.Instance())
}
// Deactivate 停止激活窗口
func (m *TCEFWindowComponent) Deactivate() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_Deactivate).Call(m.Instance())
}
// BringToTop 将窗口移至最上层
func (m *TCEFWindowComponent) BringToTop() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_BringToTop).Call(m.Instance())
}
// Maximize 最大化窗口
func (m *TCEFWindowComponent) Maximize() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_Maximize).Call(m.Instance())
}
// Minimize 最小化窗口
func (m *TCEFWindowComponent) Minimize() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_Minimize).Call(m.Instance())
}
// Restore 窗口还原
func (m *TCEFWindowComponent) Restore() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_Restore).Call(m.Instance())
}
......@@ -99,110 +129,173 @@ func (m *TCEFWindowComponent) Restore() {
// ShowMenu 显示菜单
func (m *TCEFWindowComponent) ShowMenu(menuModel *ICefMenuModel, point TCefPoint, anchorPosition consts.TCefMenuAnchorPosition) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_ShowMenu).Call(m.Instance(), uintptr(menuModel.instance), uintptr(unsafe.Pointer(&point)), uintptr(anchorPosition))
}
// CancelMenu 取消菜单
func (m *TCEFWindowComponent) CancelMenu() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_CancelMenu).Call(m.Instance())
}
// SetDraggableRegions 设置拖拽区域
func (m *TCEFWindowComponent) SetDraggableRegions(regions []TCefDraggableRegion) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetDraggableRegions).Call(m.Instance(), uintptr(int32(len(regions))), uintptr(unsafe.Pointer(&regions[0])), uintptr(int32(len(regions))))
}
// SendKeyPress 发送键盘事件
func (m *TCEFWindowComponent) SendKeyPress(keyCode int32, eventFlags uint32) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SendKeyPress).Call(m.Instance(), uintptr(keyCode), uintptr(eventFlags))
}
// SendMouseMove 发送鼠标移动事件
func (m *TCEFWindowComponent) SendMouseMove(screenX, screenY int32) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SendMouseMove).Call(m.Instance(), uintptr(screenX), uintptr(screenY))
}
// SendMouseEvents 发送鼠标事件
func (m *TCEFWindowComponent) SendMouseEvents(button consts.TCefMouseButtonType, mouseDown, mouseUp bool) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SendMouseEvents).Call(m.Instance(), uintptr(button), api.PascalBool(mouseDown), api.PascalBool(mouseUp))
}
// SetAccelerator 设置快捷键
func (m *TCEFWindowComponent) SetAccelerator(commandId, keyCode int32, shiftPressed, ctrlPressed, altPressed bool) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetAccelerator).Call(m.Instance(), uintptr(commandId), uintptr(keyCode), api.PascalBool(shiftPressed), api.PascalBool(ctrlPressed), api.PascalBool(altPressed))
}
// RemoveAccelerator 移除指定快捷键
func (m *TCEFWindowComponent) RemoveAccelerator(commandId int32) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_RemoveAccelerator).Call(m.Instance(), uintptr(commandId))
}
// RemoveAllAccelerators 移除所有快捷键
func (m *TCEFWindowComponent) RemoveAllAccelerators() {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_RemoveAllAccelerators).Call(m.Instance())
}
// SetAlwaysOnTop 设置窗口是否置顶
func (m *TCEFWindowComponent) SetAlwaysOnTop(onTop bool) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetAlwaysOnTop).Call(m.Instance(), api.PascalBool(onTop))
}
// SetFullscreen 设置窗口全屏
func (m *TCEFWindowComponent) SetFullscreen(fullscreen bool) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetFullscreen).Call(m.Instance(), api.PascalBool(fullscreen))
}
// SetBackgroundColor 设置背景色
func (m *TCEFWindowComponent) SetBackgroundColor(rect types.TCefColor) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetBackgroundColor).Call(m.Instance(), rect.ToPtr())
}
// SetBounds 获取窗口边界
// Bounds 获取窗口边界
func (m *TCEFWindowComponent) Bounds() (result *TCefRect) {
if !m.IsValid() {
return nil
}
imports.Proc(def.CEFWindowComponent_Bounds).Call(m.Instance(), uintptr(unsafe.Pointer(result)))
return
}
// SetSize 获取窗口宽高
// Size 获取窗口宽高
func (m *TCEFWindowComponent) Size() (result *TCefSize) {
if !m.IsValid() {
return nil
}
imports.Proc(def.CEFWindowComponent_Size).Call(m.Instance(), uintptr(unsafe.Pointer(result)))
return
}
// Position 获取窗口位置
func (m *TCEFWindowComponent) Position() (result *TCefPoint) {
if !m.IsValid() {
return nil
}
imports.Proc(def.CEFWindowComponent_Position).Call(m.Instance(), uintptr(unsafe.Pointer(result)))
return
}
// SetBounds 设置窗口边界
func (m *TCEFWindowComponent) SetBounds(rect *TCefRect) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetBounds).Call(m.Instance(), uintptr(unsafe.Pointer(rect)))
}
// SetSize 设置窗口宽高
func (m *TCEFWindowComponent) SetSize(size *TCefSize) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetSize).Call(m.Instance(), uintptr(unsafe.Pointer(size)))
}
// SetPosition 设置窗口位置
func (m *TCEFWindowComponent) SetPosition(point *TCefPoint) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetPosition).Call(m.Instance(), uintptr(unsafe.Pointer(point)))
}
// SetTitle 设置窗口标题
func (m *TCEFWindowComponent) SetTitle(title string) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetTitle).Call(m.Instance(), api.PascalStr(title))
}
// GetTitle 获取窗口标题
// Title 获取窗口标题
func (m *TCEFWindowComponent) Title() string {
if !m.IsValid() {
return ""
}
r1, _, _ := imports.Proc(def.CEFWindowComponent_Title).Call(m.Instance())
return api.GoStr(r1)
}
// WindowIcon 获取窗口图标
func (m *TCEFWindowComponent) WindowIcon() *ICefImage {
if !m.IsValid() {
return nil
}
var result uintptr
imports.Proc(def.CEFWindowComponent_WindowIcon).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return &ICefImage{
......@@ -212,6 +305,9 @@ func (m *TCEFWindowComponent) WindowIcon() *ICefImage {
// WindowAppIcon 获取窗口应用图标
func (m *TCEFWindowComponent) WindowAppIcon() *ICefImage {
if !m.IsValid() {
return nil
}
var result uintptr
imports.Proc(def.CEFWindowComponent_WindowAppIcon).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return &ICefImage{
......@@ -220,20 +316,28 @@ func (m *TCEFWindowComponent) WindowAppIcon() *ICefImage {
}
func (m *TCEFWindowComponent) SetWindowIcon(icon *ICefImage) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetWindowIcon).Call(m.Instance(), icon.Instance())
}
func (m *TCEFWindowComponent) checkICON(filename string) (string, error) {
if !m.IsValid() {
return "", errors.New("window component is nil")
}
ext := strings.ToLower(filepath.Ext(filename))
if ".png" != ext && ".jpeg" != ext {
return "", errors.New("only png and jpeg image formats are supported")
}
ext = ext[1:]
return ext, nil
return ext[1:], nil
}
// SetWindowIconByFile 设置窗口图标
func (m *TCEFWindowComponent) SetWindowIconByFile(scaleFactor float32, filename string) error {
if !m.IsValid() {
return errors.New("window component is nil")
}
var (
ext string
err error
......@@ -257,6 +361,9 @@ func (m *TCEFWindowComponent) SetWindowIconByFile(scaleFactor float32, filename
// SetWindowIconByFSFile 设置窗口图标
func (m *TCEFWindowComponent) SetWindowIconByFSFile(scaleFactor float32, filename string) error {
if !m.IsValid() {
return errors.New("window component is nil")
}
var (
ext string
err error
......@@ -279,11 +386,17 @@ func (m *TCEFWindowComponent) SetWindowIconByFSFile(scaleFactor float32, filenam
}
func (m *TCEFWindowComponent) SetWindowAppIcon(icon *ICefImage) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_SetWindowAppIcon).Call(m.Instance(), icon.Instance())
}
// SetWindowAppIconByFile 设置窗口应用图标
func (m *TCEFWindowComponent) SetWindowAppIconByFile(scaleFactor float32, filename string) error {
if !m.IsValid() {
return errors.New("window component is nil")
}
var (
ext string
err error
......@@ -307,6 +420,9 @@ func (m *TCEFWindowComponent) SetWindowAppIconByFile(scaleFactor float32, filena
// SetWindowAppIconByFSFile 设置窗口应用图标
func (m *TCEFWindowComponent) SetWindowAppIconByFSFile(scaleFactor float32, filename string) error {
if !m.IsValid() {
return errors.New("window component is nil")
}
var (
ext string
err error
......@@ -330,6 +446,9 @@ func (m *TCEFWindowComponent) SetWindowAppIconByFSFile(scaleFactor float32, file
// Display
func (m *TCEFWindowComponent) Display() *ICefDisplay {
if !m.IsValid() {
return nil
}
var result uintptr
imports.Proc(def.CEFWindowComponent_Display).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return &ICefDisplay{
......@@ -339,54 +458,81 @@ func (m *TCEFWindowComponent) Display() *ICefDisplay {
// ClientAreaBoundsInScreen 获取客户端所在指定屏幕位置
func (m *TCEFWindowComponent) ClientAreaBoundsInScreen() (result TCefRect) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_ClientAreaBoundsInScreen).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return
}
// WindowHandle 获取窗口句柄
func (m *TCEFWindowComponent) WindowHandle() consts.TCefWindowHandle {
if !m.IsValid() {
return 0
}
r1, _, _ := imports.Proc(def.CEFWindowComponent_WindowHandle).Call(m.Instance())
return consts.TCefWindowHandle(r1)
}
// IsClosed 是否关闭
func (m *TCEFWindowComponent) IsClosed() bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CEFWindowComponent_IsClosed).Call(m.Instance())
return api.GoBool(r1)
}
// IsActive 是否激活
func (m *TCEFWindowComponent) IsActive() bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CEFWindowComponent_IsActive).Call(m.Instance())
return api.GoBool(r1)
}
// IsAlwaysOnTop 窗口是否置顶
func (m *TCEFWindowComponent) IsAlwaysOnTop() bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CEFWindowComponent_IsAlwaysOnTop).Call(m.Instance())
return api.GoBool(r1)
}
// IsFullscreen 是否全屏
func (m *TCEFWindowComponent) IsFullscreen() bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CEFWindowComponent_IsFullscreen).Call(m.Instance())
return api.GoBool(r1)
}
// IsMaximized 是否最大化
func (m *TCEFWindowComponent) IsMaximized() bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CEFWindowComponent_IsMaximized).Call(m.Instance())
return api.GoBool(r1)
}
// IsMinimized 是否最小化
func (m *TCEFWindowComponent) IsMinimized() bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CEFWindowComponent_IsMinimized).Call(m.Instance())
return api.GoBool(r1)
}
// AddChildView 添加浏览器显示组件
func (m *TCEFWindowComponent) AddChildView(browserViewComponent *TCEFBrowserViewComponent) {
if !m.IsValid() {
return
}
imports.Proc(def.CEFWindowComponent_AddChildView).Call(m.Instance(), browserViewComponent.Instance())
}
......
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// energy - lcl window api - test
package winapi
import (
"github.com/energye/energy/v2/types"
"github.com/energye/golcl/energy/inits"
"testing"
)
func TestWinApiCallback(t *testing.T) {
inits.Init(nil, nil)
callback := NewEnumDisplayMonitorsCallback()
callback.Callback(func(hMonitor types.HMONITOR, hdcMonitor types.HDC, lprcMonitor types.Rect, dwData types.LPARAM) types.LongBool {
t.Log("EnumDisplayMonitorsCallback.Callback:", hMonitor, hdcMonitor, lprcMonitor, dwData)
return true
})
r0 := WinEnumDisplayMonitors(0, nil, callback, 0)
t.Log("R0:", r0)
dc := WinGetDC(0)
t.Log("dc:", dc)
familiesCallback := NewEnumFontFamiliesCallback()
familiesCallback.Callback(func(ELogFont *types.TagEnumLogFontA, Metric *types.TNewTextMetric, FontType types.LongInt, Data types.LPARAM) types.LongInt {
t.Log("EnumFontFamiliesCallback.Callback:", ELogFont, Metric)
return 2
})
r1 := WinEnumFontFamilies(dc, "", familiesCallback, 0)
t.Log("r1:", r1)
dc = WinGetDC(0)
t.Log("dc:", dc)
familiesExCallback := NewEnumFontFamiliesExCallback()
familiesExCallback.Callback(func(ELogFont *types.TagEnumLogFontExA, Metric *types.TNewTextMetricEx, FontType types.LongInt, Data types.LPARAM) types.LongInt {
t.Log("EnumFontFamiliesExCallback.Callback:", ELogFont, Metric)
return 2
})
r2 := WinEnumFontFamiliesEx(dc, types.LogFontA{}, familiesExCallback, 0, 0)
t.Log("r2:", r2)
}
### energy lib framework auto update
#### Divided into three modules
* liblcl
* enregy
* cef
#### Control whether to enable the module update based on enable
#### Field description
> first level node is the module name
>
> download: module download source
>
> url: module download source url template
>
> source: module download source, addrs
>
> sourceSelect: Download the address source selection, select the source based on the index, and replace it with the Url template
>
> enable: module update based on enable
>
> latest: module latest version
>
> versions: version list
>
>> forced: forced update, a significant update that applies to the current version
>>
>> content: update logs
---
#### update json template
```json
{
"liblcl": {
"download": {
"url": "https://{url}/energye/energy/releases/download/{version}/{OSARCH}.zip",
"source": [
"gitee.com",
"github.com"
],
"sourceSelect": 0
},
"enable": true,
"latest": "version.1",
"versions": {
"version.1": {
"energyVersion": "version.1",
"content": [
"update log 1",
"update log 2"
],
"forced": false
},
"version.0": {
"energyVersion": "",
"content": [
""
],
"forcede": false
}
}
},
"energy": {
"download": {
"url": "",
"source": [],
"sourceSelect": 0
},
"enable": false,
"latest": "",
"versions": {
"": {
"content": [
""
],
"forcede": false
}
}
},
"cef": {
"download": {
"url": "",
"source": [
""
],
"sourceSelect": 0
},
"enable": false,
"latest": "",
"versions": {
"": {
"content": [
""
],
"forcede": false
}
}
}
}
```
---
\ No newline at end of file
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// Package autoupdate Energy lib-lcl check auto update
package autoupdate
import (
"crypto/tls"
"encoding/json"
"github.com/energye/energy/v2/cmd/internal"
"github.com/energye/liblclbinres"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
)
type LiblclCallback func(model *Model, level int, canUpdate bool)
var (
// 检查更新开关, 默认关闭
isCheckUpdate = false
CanUpdateLiblcl LiblclCallback // 参数 model: 更新模块, Level: 更新版本级别, canUpdate: 是否有更新
)
// Model 模块
type Model struct {
CurrentVersion string `json:"-"` // 当前版本
Latest string `json:"latest"` // 最新版本
Versions map[string]VersionInfo `json:"versions"` // 当前模块所有版本集合 key=版本, value=版本信息
}
// 版本信息
type VersionInfo struct {
Content string `json:"content"` // 更新内容
DownloadSource string `json:"downloadSource"` // 下载源 逗号分隔, 数组 ["gitee.com", "github.com"]
DownloadSourceSelect int `json:"downloadSourceSelect"` // 下载源 选择
DownloadUrl string `json:"downloadUrl"` // 下载地址, https://{url}/energye/energy/releases/download/{version}/{OSARCH}.zip
Module string `json:"module"` // 模块名
BuildSupportOSArch string `json:"supportOSArch"` // 已提供构建支持的系统架构
Version string `json:"version"` // 版本
}
// CheckUpdate
// Check for updates, when isCheckUpdate is true
func CheckUpdate() {
if isCheckUpdate {
check()
}
}
// IsCheckUpdate
// Set whether to check for updates
func IsCheckUpdate(v bool) {
isCheckUpdate = v
}
func check() {
client := &http.Client{Timeout: 5 * time.Second, Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}}
request, err := http.NewRequest("GET", internal.CheckUpgradeURL, nil)
if err != nil {
println("energy check update http.NewRequest error:", err.Error())
return
}
response, err := client.Do(request)
if err != nil {
println("energy check update client.Do error:", err.Error())
return
}
defer response.Body.Close()
if data, err := ioutil.ReadAll(response.Body); err == nil {
var v map[string]*Model
if err = json.Unmarshal(data, &v); err == nil {
liblcl(v["liblcl"])
} else {
println("energy check update json.Unmarshal error", err.Error())
}
} else {
println("energy check update ioutil.ReadAl(response.Body) error", err.Error())
}
}
// liblcl Model
func liblcl(model *Model) {
currentLib := liblclbinres.LibVersion()
originLib := model.Latest
if currentLib == "" {
currentLib = "0.0.0"
}
if originLib == "" {
originLib = "0.0.0"
}
model.CurrentVersion = currentLib
can, level := compare(currentLib, originLib)
if CanUpdateLiblcl != nil {
CanUpdateLiblcl(model, level, can)
}
}
func LibLCLName(version, buildSupportOSArch string) (string, bool) {
return internal.LibLCLName(version, buildSupportOSArch)
}
// Version comparison, returns true if the current version is smaller than the remote version
func compare(current, origin string) (bool, int) {
cmajor, cminor, crevision := versionConvert(current)
omajor, ominor, orevision := versionConvert(origin)
if omajor > cmajor {
return true, 1 // major
} else if ominor > cminor {
return true, 2 // minor
} else if orevision > crevision {
return true, 3 // revision
}
return false, 0
}
// Version number conversion=>Major version, minor version, revised version
func versionConvert(ver string) (major, minor, revision int) {
ver = strings.ToLower(ver)
lastv := strings.LastIndex(ver, "v")
if lastv != -1 {
ver = ver[lastv+1:]
}
vers := strings.Split(strings.Split(ver, "-")[0], ".")
if len(vers) >= 3 {
major, _ = strconv.Atoi(vers[0])
minor, _ = strconv.Atoi(vers[1])
revision, _ = strconv.Atoi(vers[2])
} else if len(vers) >= 2 {
major, _ = strconv.Atoi(vers[0])
minor, _ = strconv.Atoi(vers[1])
} else if len(vers) >= 1 {
major, _ = strconv.Atoi(vers[0])
}
return
}
# Energy 命令行工具
## 自动配置开发环境
## 使用方式
> 需要安装[Golang](https://golang.google.cn/dl/)环境
>> go get -u github.com/energye/energy
>>
>> 进入 cmd/energy 目录
>>
>> 执行命令 "go install" 安装命令行工具
>>
>> go install
>>
>
> 三、命令参数
## Go ENERGY
### 命令行工具
### 自动安装和配置完整开发环境
> [下载地址](https://energy.yanghy.cn/course/100/1694511322285207)
>
>> energy install [path] [version]
>>
| 名称 | 描述 |
|---------|-----------------------------------------|
| install | 安装energy框架, 需要连接互联网, 自动下载CEF和Energy框架环境 |
| name | 可选参数, 目录名称, 默认EnergyFramework |
| path | 可选参数, 安装目录, 默认当前目录生成[name]文件夹 |
| version | 可选参数, 版本号v1.1.0, 默认最新版本latest |
>示例
>> 1. `energy install .`
>>
>> 2. `energy install --path=/app/energyFramework -v x.x.x .`
>>
\ No newline at end of file
> [使用说明](https://energy.yanghy.cn/course/100/1694511508415349)
......@@ -8,10 +8,6 @@ set GOARCH=amd64
set GOOS=windows
go build -ldflags "-s -w" -o energy-windows-64.exe energy.go
set GOARCH=arm64
set GOOS=windows
go build -ldflags "-s -w" -o energy-windowsarm-64.exe energy.go
set GOARCH=amd64
set GOOS=darwin
go build -ldflags "-s -w" -o energy-darwin-64 energy.go
......
upx energy-windows-32.exe
upx energy-windows-64.exe
upx energy-darwin-64
upx energy-darwinarm-64
upx energy-linux-64
upx energy-linuxarm-64
pause
\ No newline at end of file
zip -r energy-windows-32.zip energy-windows-32.exe
zip -r energy-windows-64.zip energy-windows-64.exe
zip -r energy-darwin-64.zip energy-darwin-64
zip -r energy-darwinarm-64.zip energy-darwinarm-64
zip -r energy-linux-64.zip energy-linux-64
zip -r energy-linuxarm-64.zip energy-linuxarm-64
pause
\ No newline at end of file
......@@ -8,14 +8,20 @@
//
//----------------------------------------
//Package main energy command-line
package main
import (
"fmt"
"encoding/json"
"github.com/energye/energy/v2/cmd/internal"
"github.com/energye/energy/v2/cmd/internal/command"
"github.com/energye/energy/v2/cmd/internal/consts"
"github.com/energye/energy/v2/cmd/internal/term"
"github.com/energye/energy/v2/cmd/internal/tools"
"github.com/energye/golcl/energy/homedir"
"github.com/jessevdk/go-flags"
"os"
"path/filepath"
)
var commands = []*command.Command{
......@@ -30,15 +36,26 @@ var commands = []*command.Command{
}
func main() {
wd, _ := os.Getwd()
term.GoENERGY()
termRun()
}
func termRun() {
wd := tools.CurrentExecuteDir()
cc := &command.Config{Wd: wd}
parser := flags.NewParser(cc, flags.HelpFlag|flags.PassDoubleDash)
if len(os.Args) < 2 {
parser.WriteHelp(os.Stdout)
parser.WriteHelp(term.TermOut)
//exit <- 1
os.Exit(1)
}
if extraArgs, err := parser.ParseArgs(os.Args[1:]); err != nil {
fmt.Fprint(os.Stderr, err.Error()+"\n")
if extraArgs[0] == "-v" || extraArgs[0] == "v" {
term.Section.Println(" ", term.CliVersion)
} else {
println(err.Error())
}
//exit <- 1
os.Exit(1)
} else {
switch parser.Active.Name {
......@@ -56,16 +73,70 @@ func main() {
cc.Index = 6
case "build":
cc.Index = 7
case "v":
term.Section.Println(" ", term.CliVersion)
return
}
command := commands[cc.Index]
cmd := commands[cc.Index]
if len(extraArgs) < 1 || extraArgs[len(extraArgs)-1] != "." {
fmt.Fprintf(os.Stderr, "%s\n%s", command.UsageLine, command.Long)
term.Section.Println(cmd.UsageLine, "\n", cmd.Long)
//exit <- 1
os.Exit(1)
}
fmt.Println("Energy executing:", command.Short)
if err := command.Run(cc); err != nil {
fmt.Fprint(os.Stderr, err.Error()+"\n")
term.Section.Println(cmd.Short)
readConfig(cc)
if err := cmd.Run(cc); err != nil {
term.Section.Println(err.Error())
//exit <- 1
os.Exit(1)
}
}
}
func readConfig(c *command.Config) {
home, err := homedir.Dir()
if err != nil {
term.Section.Println(err.Error())
return
}
energyDir := filepath.Join(home, ".energy")
if !tools.IsExist(energyDir) {
err = os.MkdirAll(energyDir, os.ModePerm)
if err != nil {
term.Section.Println(err.Error())
return
}
}
config := filepath.Join(energyDir, "energy.json")
if !tools.IsExist(config) {
cfg := command.EnergyConfig{
Source: command.DownloadSource{
Golang: consts.GolangDownloadSource,
CEF: "",
},
}
cfgJSON, err := json.MarshalIndent(&cfg, "", "\t")
if err != nil {
term.Section.Println(err.Error())
return
}
if err := os.WriteFile(config, cfgJSON, 0644); err != nil {
term.Section.Println(err.Error())
return
}
c.EnergyCfg = cfg
} else {
cfgJSON, err := os.ReadFile(config)
if err != nil {
term.Section.Println(err.Error())
return
}
cfg := command.EnergyConfig{}
err = json.Unmarshal(cfgJSON, &cfg)
if err != nil {
term.Section.Println(err.Error())
return
}
c.EnergyCfg = cfg
}
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package assets
import (
"embed"
"errors"
"fmt"
"github.com/energye/energy/v2/cmd/internal/project"
"github.com/energye/energy/v2/cmd/internal/tools"
"io/fs"
"os"
"path/filepath"
)
//go:embed assets
var assets embed.FS
const (
UpxVersion = "4.1.0"
)
// AssetsPath 返回配置资源目录
func AssetsPath(proj *project.Project, file string) string {
return filepath.ToSlash(filepath.Join(proj.AssetsDir, file))
}
// BuildOutPath 返回固定构建输出目录 $current/build
func BuildOutPath(proj *project.Project) string {
if proj.AppType == project.AtHelper {
return proj.ProjectPath
}
return filepath.Join(proj.ProjectPath, "build")
}
// ReadFile
// 读取文件,根据项目配置先在本地目录读取,如果读取失败,则在内置资源目录读取
func ReadFile(proj *project.Project, assetsFSPath, file string) ([]byte, error) {
var (
content []byte
err error
)
if proj != nil {
localFilePath := AssetsPath(proj, file)
content, err = os.ReadFile(localFilePath)
}
if errors.Is(err, fs.ErrNotExist) || content == nil {
content, err = assets.ReadFile(assetsFSPath + file)
if err != nil {
return nil, err
}
return content, nil
}
return content, err
}
// WriteFile 写文件到本地目录
func WriteFile(projectData *project.Project, file string, content []byte) error {
buildOutDir := BuildOutPath(projectData)
if !tools.IsExist(buildOutDir) {
if err := os.MkdirAll(buildOutDir, 0755); err != nil {
return fmt.Errorf("unable to create directory: %w", err)
}
}
targetPath := filepath.Join(buildOutDir, file)
if !projectData.Clean {
if tools.IsExist(targetPath) {
return nil
}
}
os.Remove(targetPath)
if f, err := os.OpenFile(targetPath, os.O_CREATE|os.O_WRONLY, 0755); err != nil {
return err
} else {
f.Write(content)
}
//if err := os.WriteFile(targetPath, content, 0755); err != nil {
// return err
//}
return nil
}
{
"fixed": {
"file_version": "{{.Info.FileVersion}}"
},
"info": {
"0000": {
"ProductVersion": "{{.Info.ProductVersion}}",
"CompanyName": "{{.Info.CompanyName}}",
"FileDescription": "{{.Info.ProductName}}",
"LegalCopyright": "{{.Info.Copyright}}",
"ProductName": "{{.Info.ProductName}}",
"Comments": "{{.Info.Comments}}"
}
}
}
\ No newline at end of file
{
"name": "{{.Name}}",
"projectPath": "{{.ProjectPath}}",
"frameworkPath": "{{.FrameworkPath}}",
"assetsDir": "assets",
"outputFilename": "{{.OutputFilename}}",
"plist": {
"icon": "{{.ProjectPath}}/resources/icon.png",
"companyName": "{{.CompanyName}}",
"productName": "{{.ProductName}}",
"locals": [
"zh_CN",
"en"
],
"cfBundleVersion": "1.0.0",
"cfBundleShortVersionString": "1.0.0",
"copyright": "Copyright.....",
"comments": "Built using ENERGY (https://github.com/energye/energy)",
"include": [],
"exclude": ["cache"]
},
"author": {
"name": "yanghy",
"email": "snxamdf@126.com"
}
}
{
"name": "{{.Name}}",
"projectPath": "{{.ProjectPath}}",
"frameworkPath": "{{.FrameworkPath}}",
"assetsDir": "assets",
"outputFilename": "{{.OutputFilename}}",
"info": {
"icon": "{{.ProjectPath}}/resources/icon.png",
"companyName": "{{.CompanyName}}",
"productName": "{{.ProductName}}",
"productVersion": "1.0.0",
"comments": "Built using ENERGY (https://github.com/energye/energy)"
},
"dpkg": {
"include": [],
"exclude": ["cache"],
"package": "com.{{.CompanyName}}.{{.CompanyName}}",
"homepage": "https://github.com/energye/energy",
"compress": "7zz",
"compressName": "framework.7z"
},
"author": {
"name": "yanghy",
"email": "snxamdf@126.com"
}
}
{
"name": "{{.Name}}",
"projectPath": "{{.ProjectPath}}",
"frameworkPath": "{{.FrameworkPath}}",
"assetsDir": "assets",
"outputFilename": "{{.OutputFilename}}",
"info": {
"icon": "{{.ProjectPath}}/resources/icon.ico",
"companyName": "{{.CompanyName}}",
"productName": "{{.ProductName}}",
"fileVersion": "1.0.0",
"productVersion": "1.0.0",
"copyright": "Copyright.....",
"comments": "Built using ENERGY (https://github.com/energye/energy)",
"fileDescription": "Built using ENERGY (https://github.com/energye/energy)"
},
"nsis": {
"include": [],
"exclude": ["cache"],
"icon": "{{.ProjectPath}}/resources/icon.ico",
"unIcon": "{{.ProjectPath}}/resources/icon.ico",
"license": "",
"language": "english",
"requestExecutionLevel": "admin",
"compress": "7za",
"compressName": "framework.7z"
},
"author": {
"name": "yanghy",
"email": "snxamdf@126.com"
}
}
......@@ -5,6 +5,11 @@
>> cn: 资源存放目录, 可自定义目录名
>>
>> en: Resource storage directory, customizable directory name
>
> build
>> 自动生成目录: 用于编译、构建、生成安装包
>>
>> Automatically generate directory: used for compiling, building, and generating installation packages
## 文件说明 - File description
> energy.json
......@@ -18,9 +23,9 @@
>> en: go module dependency management, has an unchangeable file name.
>
> main.go
>> cn: go应用启用入口文件
>> cn: go energy应用启动入口文件
>>
>> en: go application enables the entry file
>> en: go energy application enables the entry file
>
> go.sum No need to change
......@@ -51,4 +56,4 @@
> 2. 执行制作安装包命令 - Run the create installation package command
>> `energy package .`
>>
>> [Reference link]()
\ No newline at end of file
>> [Reference link](https://energy.yanghy.cn/course/100/1694511508415349)
\ No newline at end of file
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Go Energy</title>
<style>
.logo {
width: 300px;
height: 300px;
margin: 40px auto 0;
}
.logo img {
width: 100%;
}
.module {
text-align: center;
padding: 0 20px;
margin: 0px auto;
color: #000;
}
.module .content {
margin-right: 20px;
text-align: center;
}
.module p {
color: #999;
}
</style>
</head>
<body>
<div class="logo">
<img src="icon.png">
</div>
<div class="module">
<div class="content">
<p style="font-weight: bold; font-size: 14px; color: #000;">Welcome to your new project!</p>
<p>OS Info: <span id="osInfo">--</span></p>
</div>
<div class="content">
<p style="font-weight: bold; font-size: 14px; color: #000">Getting start</p>
<a href="https://github.com/energye/energy">Github</a>
<a href="https://energy.yanghy.cn/course/100/0">Course</a>
<a href="https://energy.yanghy.cn/example/200/0">Example</a>
<a href="https://energy.yanghy.cn/document/300/0">Document</a>
</div>
</div>
<script>
// js on osInfo
ipc.on("osInfo", function (os) {
document.getElementById("osInfo").innerText = os;
});
// js emit send count++
let count = 0;
setInterval(function () {
count++
ipc.emit("count", [count]);
}, 1000)
</script>
</body>
</html>
......@@ -3,7 +3,10 @@ package main
import (
"embed"
"github.com/energye/energy/v2/cef"
"github.com/energye/energy/v2/cef/ipc"
"github.com/energye/energy/v2/pkgs/assetserve"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/rtl/version"
)
//go:embed resources
......@@ -13,7 +16,7 @@ func main() {
//Global initialization must be called
cef.GlobalInit(nil, &resources)
//Create an application
cefApp := cef.NewApplication()
app := cef.NewApplication()
//http's url
cef.BrowserWindow.Config.Url = "http://localhost:22022/index.html"
//Security key and value settings for built-in static resource services
......@@ -26,6 +29,30 @@ func main() {
server.Assets = &resources //Assets resources
go server.StartHttpServer()
})
// run main process and main thread
cef.BrowserWindow.SetBrowserInit(browserInit)
//run app
cef.Run(cefApp)
cef.Run(app)
}
// run main process and main thread
func browserInit(event *cef.BrowserEvent, window cef.IBrowserWindow) {
// index.html ipc.emit("count", [count++])
ipc.On("count", func(value int) {
println("count", value)
})
// page load end
event.SetOnLoadEnd(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, httpStatusCode int32, window cef.IBrowserWindow) {
// index.html, ipc.on("osInfo", function(){...})
println("osInfo", version.OSVersion.ToString())
ipc.Emit("osInfo", version.OSVersion.ToString())
var windowType string
if window.IsLCL() {
windowType = "LCL"
} else {
windowType = "VF"
}
// index.html, ipc.on("windowType", function(){...});
ipc.Emit("windowType", windowType)
})
}
package main
import (
"embed"
"github.com/energye/energy/v2/cef"
"github.com/energye/energy/v2/cef/ipc"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/rtl/version"
)
//go:embed resources
var resources embed.FS
func main() {
//Global initialization must be called
cef.GlobalInit(nil, &resources)
//Create an application
app := cef.NewApplication()
//Local load resources
cef.BrowserWindow.Config.LocalResource(cef.LocalLoadConfig{
ResRootDir: "resources",
FS: &resources,
}.Build())
// run main process and main thread
cef.BrowserWindow.SetBrowserInit(browserInit)
//run app
cef.Run(app)
}
// run main process and main thread
func browserInit(event *cef.BrowserEvent, window cef.IBrowserWindow) {
// index.html ipc.emit("count", [count++])
ipc.On("count", func(value int) {
println("count", value)
})
// page load end
event.SetOnLoadEnd(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, httpStatusCode int32, window cef.IBrowserWindow) {
// index.html, ipc.on("osInfo", function(){...})
println("osInfo", version.OSVersion.ToString())
ipc.Emit("osInfo", version.OSVersion.ToString())
var windowType string
if window.IsLCL() {
windowType = "LCL"
} else {
windowType = "VF"
}
// index.html, ipc.on("windowType", function(){...});
ipc.Emit("windowType", windowType)
})
}
#!/bin/sh
message()
{
TITLE="Cannot start ENERGY_HOME"
if [ -n "$(command -v zenity)" ]; then
zenity --error --title="$TITLE" --text="$1" --no-wrap
elif [ -n "$(command -v kdialog)" ]; then
kdialog --error "$1" --title "$TITLE"
elif [ -n "$(command -v notify-send)" ]; then
notify-send "ERROR: $TITLE" "$1"
elif [ -n "$(command -v xmessage)" ]; then
xmessage -center "ERROR: $TITLE: $1"
else
printf "ERROR: %s\n%s\n" "$TITLE" "$1"
fi
}
if [ -z "$ENERGY_HOME" ] || [ ! -d "$ENERGY_HOME" ]; then
message "No CEF found. Please make sure \$ENERGY_HOME point to valid installation."
exit 1
fi
LIBCEF="$ENERGY_HOME/libcef.so"
if [ ! -e "$LIBCEF" ]; then
message "No CEF libcef.so found. Please make sure \$ENERGY_HOME point to valid installation."
exit 1
fi
# fix: linux arm: Error loading libcef.so
# temp LD_PRELOAD, Load libcef.so correctly
export LD_PRELOAD="$LIBCEF"
# go run xxx.go
exec go run $1
\ No newline at end of file
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleName</key>
<string>{{.Info.ProductName}}</string>
<key>CFBundleExecutable</key>
<string>{{.OutputFilename}}</string>
<key>CFBundleName</key>
<string>{{.Name}}</string>
<key>CFBundleLocalizations</key>
<array>{{range $i,$value := .PList.Locals }}
<string>{{$value}}</string>{{end}}
</array>
<key>CFBundleIdentifier</key>
<string>com.energy.{{.Name}}</string>
<string>com.{{.PList.CompanyName}}.{{.PList.ProductName}}</string>
<key>CFBundleVersion</key>
<string>{{.Info.ProductVersion}}</string>
<key>CFBundleGetInfoString</key>
<string>{{.Info.Comments}}</string>
<string>{{.PList.CFBundleVersion}}</string>
<key>CFBundleShortVersionString</key>
<string>{{.Info.ProductVersion}}</string>
<string>{{.PList.CFBundleShortVersionString}}</string>
<key>CFBundleGetInfoString</key>
<string>{{.PList.Comments}}</string>
<key>CFBundleIconFile</key>
<string>iconfile</string>
<string>{{.PList.Icon}}</string>
<key>NSHumanReadableCopyright</key>
<string>{{.PList.Copyright}}</string>
<key>LSUIElement</key>
<{{.PList.LSUIElement}}/>
<key>LSMinimumSystemVersion</key>
<string>10.13.0</string>
<key>NSHighResolutionCapable</key>
<string>true</string>
<key>NSHumanReadableCopyright</key>
<string>{{.Info.Copyright}}</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSPrincipalClass</key>
<string>TCrCocoaApplication</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>*</string>
</array>
<key>CFBundleTypeOSTypes</key>
<array>
<string>fold</string>
<string>disk</string>
<string>****</string>
</array>
</dict>
</array>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>
\ No newline at end of file
[Desktop Entry]
Type=Application
Exec={{.Name}}
Terminal=false
Name={{.Name}}
Icon={{.Name}}
Exec={{.Exec}}
Icon={{.Icon}}
Comment={{.Comments}}
Encoding=UTF-8
Categories=Utility;
\ No newline at end of file
Package: {{.Dpkg.Package}}
Version: {{.Info.ProductVersion}}
Section: Application
Priority: optional
Architecture: {{.Arch}}
Maintainer: {{.Author.Name}} <{{.Author.Email}}>
Description: {{.Info.Comments}}
Homepage: {{.Dpkg.Homepage}}
#!/bin/sh
message()
{
TITLE="Cannot start {{.EXECUTE}}"
if [ -n "$(command -v zenity)" ]; then
zenity --error --title="$TITLE" --text="$1" --no-wrap
elif [ -n "$(command -v kdialog)" ]; then
kdialog --error "$1" --title "$TITLE"
elif [ -n "$(command -v notify-send)" ]; then
notify-send "ERROR: $TITLE" "$1"
elif [ -n "$(command -v xmessage)" ]; then
xmessage -center "ERROR: $TITLE: $1"
else
printf "ERROR: %s\n%s\n" "$TITLE" "$1"
fi
}
# install path libcef.so
LIBCEF="{{.INSTALLPATH}}/libcef.so"
if [ ! -e "$LIBCEF" ]; then
message "No CEF libcef.so found. Please make sure CEF point to valid installation."
exit 1
fi
# fix: linux arm: Error loading libcef.so
# temp LD_PRELOAD, Load libcef.so correctly
export LD_PRELOAD="$LIBCEF"
# Execution File Name
STARTUP="{{.INSTALLPATH}}/{{.EXECUTE}}"
exec $STARTUP
\ No newline at end of file
......@@ -2,20 +2,21 @@ Unicode true
!include "installer-tools.nsh"
; The version information for this two must consist of 4 parts
VIProductVersion "${INFO_PRODUCTVERSION}.0"
VIFileVersion "${INFO_PRODUCTVERSION}.0"
VIProductVersion "${INFO_ProductVersion}.0"
VIFileVersion "${INFO_FileVersion}.0"
VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}"
VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer"
VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}"
VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
VIAddVersionKey "ProductName" "${INFO_ProductName}"
VIAddVersionKey "CompanyName" "${INFO_CompanyName}"
VIAddVersionKey "FileDescription" "${INFO_FileDescription}"
VIAddVersionKey "ProductVersion" "${INFO_ProductVersion}"
VIAddVersionKey "FileVersion" "${INFO_FileVersion}"
VIAddVersionKey "LegalCopyright" "${INFO_Copyright}"
!include "MUI2.nsh"
!define MUI_ICON "..\icon.ico"
!define MUI_UNICON "..\icon.ico"
!define MUI_ICON "${INFO_Icon}" ;"..\icon.ico"
!define MUI_UNICON "${INFO_UnIcon}" ;"..\icon.ico"
; !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314
!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps
!define MUI_ABORTWARNING # This will warn the user if they exit from the installer.
......@@ -26,8 +27,8 @@ VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page.
; LICENSE Page
!ifdef ARG_ENERGY_PAGE_LICENSE
!insertmacro MUI_PAGE_LICENSE "${ARG_ENERGY_PAGE_LICENSE}" # Add a LICENSE page to the installer
!ifdef ENERGY_PAGE_LICENSE
!insertmacro MUI_PAGE_LICENSE "${ENERGY_PAGE_LICENSE}" # Add a LICENSE page to the installer
!endif
!insertmacro MUI_PAGE_DIRECTORY # In which folder install page.
......@@ -42,9 +43,9 @@ VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
;!uninstfinalize 'signtool --file "%1"'
;!finalize 'signtool --file "%1"'
Name "${INFO_PRODUCTNAME}"
OutFile ".\${INFO_PROJECTNAME}-installer.exe" # Name of the installer's file.
InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder).
Name "${INFO_ProductName}"
OutFile ".\${INFO_ProjectName}-installer.exe" # Name of the installer's file.
InstallDir "$PROGRAMFILES64\${INFO_CompanyName}\${INFO_ProductName}" # Default installing folder ($PROGRAMFILES is Program Files folder).
ShowInstDetails show # This will always show the installation details.
Function .onInit
......@@ -57,8 +58,10 @@ Section
!insertmacro energy.files
CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
CreateShortcut "$SMPROGRAMS\${INFO_ProductName}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
CreateShortCut "$DESKTOP\${INFO_ProductName}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
!insertmacro energy.compressNsis7z
!insertmacro energy.writeUninstaller
SectionEnd
......@@ -70,8 +73,8 @@ Section "uninstall"
RMDir /r $INSTDIR
Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk"
Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
Delete "$SMPROGRAMS\${INFO_ProductName}.lnk"
Delete "$DESKTOP\${INFO_ProductName}.lnk"
!insertmacro energy.deleteUninstaller
SectionEnd
......@@ -4,55 +4,59 @@
!include "WinVer.nsh"
!include "FileFunc.nsh"
!ifndef INFO_PROJECTNAME
!define INFO_PROJECTNAME "{{.Name}}"
!endif
!ifndef INFO_COMPANYNAME
!define INFO_COMPANYNAME "{{.Info.CompanyName}}"
!endif
!ifndef INFO_PRODUCTNAME
!define INFO_PRODUCTNAME "{{.Info.ProductName}}"
!endif
!ifndef INFO_PRODUCTVERSION
!define INFO_PRODUCTVERSION "{{.Info.ProductVersion}}"
!endif
!ifndef INFO_COPYRIGHT
!define INFO_COPYRIGHT "{{.Info.Copyright}}"
!endif
!ifndef PRODUCT_EXECUTABLE
!define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"
!endif
!ifndef UNINST_KEY_NAME
!define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
!endif
!define INFO_ProjectName "{{.Name}}"
!define INFO_CompanyName "{{.Info.CompanyName}}"
!define INFO_ProductName "{{.Info.ProductName}}"
!define INFO_FileVersion "{{.Info.FileVersion}}"
!define INFO_ProductVersion "{{.Info.ProductVersion}}"
!define INFO_FileDescription "{{.Info.FileDescription}}"
!define INFO_Copyright "{{.Info.Copyright}}"
!define PRODUCT_EXECUTABLE "${INFO_ProjectName}.exe"
!define UNINST_KEY_NAME "${INFO_CompanyName}${INFO_ProductName}"
!define INFO_Icon "{{.NSIS.Icon}}"
!define INFO_UnIcon "{{.NSIS.UnIcon}}"
!define ENERGY_LANGUAGE "{{.NSIS.Language}}"
!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}"
!ifndef REQUEST_EXECUTION_LEVEL
!define REQUEST_EXECUTION_LEVEL "admin"
!endif
{{if .NSIS.License}}
!define ENERGY_PAGE_LICENSE "{{.NSIS.License}}" ; license.txt path
{{end}}
RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
{{if .NSIS.RequestExecutionLevel}}
!define REQUEST_EXECUTION_LEVEL "{{.NSIS.RequestExecutionLevel}}"
RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" ; admin or ""
{{end}}
!ifdef ARG_ENERGY_LANGUAGE
!define ENERGY_LANGUAGE "${ARG_ENERGY_LANGUAGE}" # customer
!else
!define ENERGY_LANGUAGE "English" # default
!endif
!macro energy.files
File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_ENERGY_BINARY}" ; energy app.exe path, ..\..\app.exe
;File /r "${ARG_ENERGY_CEF_FRAMEWORK}" ; cef framework path, ENERGY_HOME=/to/cef/path
File "/oname=${PRODUCT_EXECUTABLE}" "{{.ProjectPath}}\{{.Name}}.exe" ; app.exe path, ..\..\app.exe
{{if .NSIS.CompressFile}}
File "{{.NSIS.CompressFile}}"
{{else if .FrameworkPath}}
File /r "{{.FrameworkPath}}\*.*"
{{end}}
{{range $i,$path := .NSIS.Include }}
File /r "{{$path}}"{{end}}
!macroend
!macro energy.compressNsis7z
{{if .NSIS.UseCompress}} ;CEF
Nsis7z::ExtractWithCallback "$INSTDIR\{{.NSIS.CompressName}}"
Delete "$OUTDIR\{{.NSIS.CompressName}}"
{{end}}
!macroend
!macro energy.writeUninstaller
WriteUninstaller "$INSTDIR\uninstall.exe"
SetRegView 64
WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}"
WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}"
WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}"
WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_CompanyName}"
WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_ProductName}"
WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_ProductVersion}"
WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}"
WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
......
......@@ -8,27 +8,19 @@
//
//----------------------------------------
// V8 JSValue JSDouble 类型实现
//go:build linux && amd64
// +build linux,amd64
package bind
package assets
type JSDouble interface {
JSValue
AsDouble() JSDouble
DoubleValue() float64
}
type jsDouble struct {
V8Value
}
import (
"embed"
"io/fs"
)
func (m *jsDouble) AsDouble() JSDouble {
if m.IsDouble() {
return m
}
return nil
}
//go:embed upx/upx-linux-amd64
var upx embed.FS
func (m *jsDouble) DoubleValue() float64 {
return m.JsonData.Float()
func UpxBytes() (fs.File, error) {
return upx.Open("upx/upx-linux-amd64")
}
......@@ -8,27 +8,19 @@
//
//----------------------------------------
// V8 JSValue JSInteger 类型实现
//go:build linux && arm64
// +build linux,arm64
package bind
package assets
type JSInteger interface {
JSValue
AsInteger() JSInteger
IntegerValue() int
}
type jsInteger struct {
V8Value
}
import (
"embed"
"io/fs"
)
func (m *jsInteger) AsInteger() JSInteger {
if m.IsInteger() {
return m
}
return nil
}
//go:embed upx/upx-linux-arm64
var upx embed.FS
func (m *jsInteger) IntegerValue() int {
return m.JsonData.Int()
func UpxBytes() (fs.File, error) {
return upx.Open("upx/upx-linux-arm64")
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
//go:build darwin || (windows && arm64)
// +build darwin windows,arm64
package assets
import (
"errors"
"io/fs"
)
func UpxBytes() (fs.File, error) {
return nil, errors.New("not support")
}
......@@ -8,27 +8,19 @@
//
//----------------------------------------
// V8 JSValue JSBoolean 类型实现
//go:build windows && 386
// +build windows,386
package bind
package assets
type JSBoolean interface {
JSValue
AsBoolean() JSBoolean
BooleanValue() bool
}
type jsBoolean struct {
V8Value
}
import (
"embed"
"io/fs"
)
func (m *jsBoolean) AsBoolean() JSBoolean {
if m.IsBoolean() {
return m
}
return nil
}
//go:embed upx/upx-windows-amd32.exe
var upx embed.FS
func (m *jsBoolean) BooleanValue() bool {
return m.JsonData.Bool()
func UpxBytes() (fs.File, error) {
return upx.Open("upx/upx-windows-amd32.exe")
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
//go:build windows && amd64
// +build windows,amd64
package assets
import (
"embed"
"io/fs"
)
//go:embed upx/upx-windows-amd64.exe
var upx embed.FS
func UpxBytes() (fs.File, error) {
return upx.Open("upx/upx-windows-amd64.exe")
}
此差异已折叠。
......@@ -12,7 +12,10 @@
package internal
import "github.com/energye/energy/v2/cmd/internal/command"
import (
"github.com/energye/energy/v2/cmd/internal/build"
"github.com/energye/energy/v2/cmd/internal/command"
)
var CmdBuild = &command.Command{
UsageLine: "build",
......@@ -28,5 +31,5 @@ func init() {
}
func runBuild(c *command.Config) error {
return nil
return build.Build(c)
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package build
import (
"github.com/energye/energy/v2/cmd/internal/command"
"github.com/energye/energy/v2/cmd/internal/project"
)
const (
assetsFSPath = "assets/build/"
)
func Build(c *command.Config) error {
// 读取项目配置文件 energy.json 在main函数目录
if proj, err := project.NewProject(c.Build.Path); err != nil {
return err
} else {
proj.TempDll = c.Build.TempDll
return build(c, proj)
}
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
//go:build darwin
// +build darwin
package build
import (
"github.com/energye/energy/v2/cmd/internal/command"
"github.com/energye/energy/v2/cmd/internal/project"
"github.com/energye/energy/v2/cmd/internal/term"
"github.com/energye/energy/v2/cmd/internal/tools"
toolsCommand "github.com/energye/golcl/tools/command"
"strings"
)
func build(c *command.Config, proj *project.Project) (err error) {
// go build
cmd := toolsCommand.NewCMD()
cmd.Dir = proj.ProjectPath
cmd.IsPrint = false
term.Section.Println("Building", proj.OutputFilename)
var args = []string{"build"}
if proj.TempDll {
args = append(args, "--tags=tempdll")
}
args = append(args, "-ldflags", "-s -w")
args = append(args, "-o", proj.OutputFilename)
cmd.Command("go", args...)
cmd.Command("strip", proj.OutputFilename)
// upx
if c.Build.Upx && tools.CommandExists("upx") {
term.Section.Println("Upx compression")
args = []string{"--best", "--no-color", "--no-progress", proj.OutputFilename}
if c.Build.UpxFlag != "" {
args = strings.Split(c.Build.UpxFlag, " ")
args = append(args, proj.OutputFilename)
}
cmd.Command("upx", args...)
} else if c.Build.Upx {
term.Logger.Error("upx command not found", term.Logger.Args("install-upx", "brew install upx"))
}
cmd.Close()
if err == nil {
term.Section.Println("Build Successfully")
}
return nil
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
//go:build linux
// +build linux
package build
import (
"github.com/energye/energy/v2/cmd/internal/command"
"github.com/energye/energy/v2/cmd/internal/project"
"github.com/energye/energy/v2/cmd/internal/term"
"github.com/energye/energy/v2/cmd/internal/tools"
toolsCommand "github.com/energye/golcl/tools/command"
"os"
"strings"
)
func build(c *command.Config, proj *project.Project) (err error) {
// go build
cmd := toolsCommand.NewCMD()
cmd.Dir = proj.ProjectPath
cmd.IsPrint = false
term.Section.Println("Building", proj.OutputFilename)
var args = []string{"build"}
if proj.TempDll {
c.Build.Gtk = strings.ToLower(c.Build.Gtk)
if c.Build.Gtk != "gtk3" && c.Build.Gtk != "gtk2" {
term.Logger.Error("Compiling and enabling TempDll. gtk can only be gtk2 or gtk3")
os.Exit(1)
}
args = append(args, "--tags=tempdll "+c.Build.Gtk)
}
args = append(args, "-ldflags", "-s -w")
args = append(args, "-o", proj.OutputFilename)
cmd.Command("go", args...)
cmd.Command("strip", proj.OutputFilename)
// upx
if c.Build.Upx && tools.CommandExists("upx") {
term.Section.Println("Upx compression")
args = []string{"--best", "--no-color", "--no-progress", proj.OutputFilename}
if c.Build.UpxFlag != "" {
args = strings.Split(c.Build.UpxFlag, " ")
args = append(args, proj.OutputFilename)
}
cmd.Command("upx", args...)
}
cmd.Close()
if err == nil {
term.Section.Println("Build Successfully")
}
return nil
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。