feat: add a new awesome feature
This commit is contained in:
151
CHANGELOG.en.md
Normal file
151
CHANGELOG.en.md
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to the StellarX project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
[中文文档](CHANGELOG.md)
|
||||||
|
|
||||||
|
## [v2.0.1] - 2025-10-03
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- New example: 32-bit register viewer tool implemented based on StellarX (supports bit inversion, left shift, right shift, hexadecimal/decimal signed/unsigned toggle, grouped binary display).
|
||||||
|
- Example path: `examples/register-viewer/`
|
||||||
|
- `TextBox` added `setText` API, allowing external setting of text box content
|
||||||
|
- `TextBox::setText` API modified: immediately calls `draw` method to redraw after setting text
|
||||||
|
- `Button` added `setButtonClick` API, allowing external functions to modify button click state and execute corresponding callback functions
|
||||||
|
- ==All documents updated with corresponding English versions(.en)==
|
||||||
|
|
||||||
|
## [v2.0.0] - 2025-09-21
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
v2.0.0 is a major release. This release introduces dialog and message box factory (Dialog / MessageBox), with several important fixes and improvements to event distribution, API semantics, and internal resource management.
|
||||||
|
|
||||||
|
Some APIs/behaviors have breaking changes that are not backward compatible.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Dialog System**:
|
||||||
|
- Added `Dialog` class, inheriting from `Canvas`, for building modal and non-modal dialogs
|
||||||
|
- Added `MessageBox` factory class, providing two convenient APIs: `ShowModal` (synchronous blocking) and `ShowAsync` (asynchronous callback)
|
||||||
|
- Supports six standard message box types: `OK`, `OKCancel`, `YesNo`, `YesNoCancel`, `RetryCancel`, `AbortRetryIgnore`
|
||||||
|
- Automatically handles dialog layout, background saving and restoration, event propagation, and lifecycle management
|
||||||
|
|
||||||
|
- **Enhanced Event System**:
|
||||||
|
- All controls' `handleEvent` methods now return `bool` type, indicating whether the event was consumed
|
||||||
|
- Introduced event consumption mechanism, supporting finer-grained event propagation control
|
||||||
|
- Window class event loop now prioritizes dialog event processing
|
||||||
|
|
||||||
|
- **Control State Management**:
|
||||||
|
- Control base class added `dirty` flag and `setDirty()` method, uniformly managing redraw state
|
||||||
|
- All controls now implement `IsVisible()` and `model()` methods
|
||||||
|
|
||||||
|
- **API Enhancements**:
|
||||||
|
- Button class added `setButtonFalseColor()` method
|
||||||
|
- TextBox class `setMaxCharLen()` now accepts `size_t` type parameter
|
||||||
|
- Window class added dialog management methods and duplicate detection mechanism
|
||||||
|
|
||||||
|
### Breaking Changes
|
||||||
|
- **API Signature Changes**:
|
||||||
|
- All controls' `handleEvent(const ExMessage& msg)` method changed from returning `void` to returning `bool`
|
||||||
|
- Control base class added pure virtual functions `IsVisible() const` and `model() const`, all derived classes must implement them
|
||||||
|
|
||||||
|
- **Resource Management Changes**:
|
||||||
|
- Control base class style saving changed from stack objects to heap objects, managed using pointers
|
||||||
|
- Enhanced resource release safety, all resources are properly released in destructors
|
||||||
|
|
||||||
|
- **Event Handling Logic**:
|
||||||
|
- Window's `runEventLoop()` method completely rewritten, now prioritizes dialog events
|
||||||
|
- Introduced event consumption mechanism, events do not continue propagating after being consumed
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Memory Management**:
|
||||||
|
- Fixed memory leak issue in `Button::setFillIma()`
|
||||||
|
- Fixed resource release issues in Control base class destructor
|
||||||
|
- Fixed background image resource management issues in Dialog class
|
||||||
|
|
||||||
|
- **Layout and Rendering**:
|
||||||
|
- Fixed pagination calculation, column width, and row height boundary issues in `Table` component
|
||||||
|
- Fixed layout disorder caused by `pX` coordinate accumulation error in `Table`
|
||||||
|
- Fixed dirty determination issue in `Canvas::draw()` that prevented child controls from being drawn
|
||||||
|
- Fixed asymmetric call issues between `TextBox::draw()` and `restoreStyle()`
|
||||||
|
|
||||||
|
- **Event Handling**:
|
||||||
|
- Fixed window event distribution logic to ensure dialog/top-level controls prioritize event processing
|
||||||
|
- Fixed delayed state updates when mouse moves out of button area
|
||||||
|
- Fixed race conditions in non-modal dialog event handling
|
||||||
|
|
||||||
|
- **Other Issues**:
|
||||||
|
- Fixed potential errors in text measurement and rendering
|
||||||
|
- Fixed incomplete background restoration after dialog closure
|
||||||
|
- Fixed z-order management issues in multi-dialog scenarios
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **Code Quality**:
|
||||||
|
- Refactored numerous internal APIs, enhancing exception safety and maintainability
|
||||||
|
- Used smart pointers and modern C++ features to replace raw new/delete
|
||||||
|
- Unified code style and naming conventions
|
||||||
|
|
||||||
|
- **Performance Optimization**:
|
||||||
|
- Optimized event processing flow, reducing unnecessary redraws
|
||||||
|
- Improved dialog background saving and restoration mechanism
|
||||||
|
- Reduced memory allocation and copy operations
|
||||||
|
|
||||||
|
- **Documentation and Examples**:
|
||||||
|
- Added detailed usage examples for all new features
|
||||||
|
- Improved code comments and API documentation
|
||||||
|
- Updated README and CHANGELOG to reflect latest changes
|
||||||
|
|
||||||
|
## [1.1.0] - 2025-09-08
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Window Class API Enhancements**:
|
||||||
|
- Added complete getter method set, improving class encapsulation and usability
|
||||||
|
- `getHwnd()` - Get window handle for integration with native Windows API
|
||||||
|
- `getWidth()` - Get window width
|
||||||
|
- `getHeight()` - Get window height
|
||||||
|
- `getHeadline()` - Get window title
|
||||||
|
- `getBkcolor()` - Get window background color
|
||||||
|
- `getBkImage()` - Get window background image pointer
|
||||||
|
- `getControls()` - Get reference to control management container, allowing iteration and manipulation of added controls
|
||||||
|
|
||||||
|
### Improved
|
||||||
|
- **API Consistency**: Provided symmetric setter and getter methods for all important attributes
|
||||||
|
- **Code Documentation**: Further improved class comments, making them clearer and more professional
|
||||||
|
|
||||||
|
## [1.0.0] - 2025-09-08
|
||||||
|
|
||||||
|
### Release Summary
|
||||||
|
First stable release
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- First stable version of StellarX framework
|
||||||
|
- Complete control library: Button, Label, TextBox, Canvas, Table, and Window
|
||||||
|
- CMake-based build system
|
||||||
|
- Detailed documentation and example code
|
||||||
|
- **Explicit declaration: This framework is specifically designed for Windows platform**
|
||||||
|
|
||||||
|
### Released
|
||||||
|
- **First release of pre-compiled binary library files**, facilitating quick integration without compiling from source
|
||||||
|
- Provided release packages include:
|
||||||
|
- `StellarX-v1.0.0-x64-Windows-msvc-x64.zip`
|
||||||
|
- **Build Environment**: Visual Studio 2022 (MSVC v143)
|
||||||
|
- **Architecture**: x64 (64-bit)
|
||||||
|
- **Runtime Library**: `/MD`
|
||||||
|
- **Build Modes**: `Release | Debug`
|
||||||
|
- **Contents**: Includes all necessary header files (`include/`) and static library files (`lib/StellarX-Debug.lib StellarX-Release.lib`)
|
||||||
|
|
||||||
|
### Core Features
|
||||||
|
- Modular design following SOLID principles
|
||||||
|
- Unified control interface (`draw()` and `handleEvent()`)
|
||||||
|
- Support for multiple control shapes and styles
|
||||||
|
- Custom event handling callbacks
|
||||||
|
- Lightweight design with no external dependencies
|
||||||
|
|
||||||
|
## [0.1.0] - 2025-08-15
|
||||||
|
### Added
|
||||||
|
- Initial project structure and core architecture
|
||||||
|
- Control base class and basic event handling system
|
||||||
|
- Basic examples and documentation setup
|
||||||
@@ -5,12 +5,18 @@ StellarX 项目所有显著的变化都将被记录在这个文件中。
|
|||||||
格式基于 [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
格式基于 [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
并且本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
并且本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
||||||
|
|
||||||
## [v2.0.1] - 2025 - 10 - 01
|
[English document](CHANGELOG.en.md)
|
||||||
|
|
||||||
|
## [v2.0.1] - 2025 - 10 - 03
|
||||||
|
|
||||||
### 新增
|
### 新增
|
||||||
|
|
||||||
|
- 新增示例:基于 StellarX 实现的 32 位寄存器查看工具(支持位取反、左移、右移,十六进制/十进制带符号/无符号切换,分组二进制显示)。
|
||||||
|
- 示例路径:`examples/register-viewer/`
|
||||||
- `TextBox`新增`setText`API,可在外部设置文本框内容
|
- `TextBox`新增`setText`API,可在外部设置文本框内容
|
||||||
|
- `TextBox::setText`API修改:在设置文本后立即调用`draw`方法重绘
|
||||||
- `Button`新增`setButtonClick`API,允许通过外部函数修改按钮的点击状态,并执行相应的回调函数
|
- `Button`新增`setButtonClick`API,允许通过外部函数修改按钮的点击状态,并执行相应的回调函数
|
||||||
|
- ==所有文档更新对应英文版本==
|
||||||
|
|
||||||
## [v2.0.0] - 2025-09-21
|
## [v2.0.0] - 2025-09-21
|
||||||
|
|
||||||
|
|||||||
94
CONTRIBUTING.en.md
Normal file
94
CONTRIBUTING.en.md
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
# Contributing to StellarX
|
||||||
|
|
||||||
|
Thank you for your interest in contributing to StellarX! This document provides guidelines and steps for contributing.
|
||||||
|
|
||||||
|
StellarX is a C++ GUI framework built for the **Windows platform**, based on the EasyX graphics library.
|
||||||
|
|
||||||
|
## Development Environment Setup
|
||||||
|
|
||||||
|
1. Install Visual Studio 2019 or later
|
||||||
|
2. Install the corresponding version of EasyX graphics library
|
||||||
|
3. Install CMake 3.12 or later
|
||||||
|
4. Clone the project repository
|
||||||
|
5. Use CMake to generate the solution and compile
|
||||||
|
|
||||||
|
## How to Contribute
|
||||||
|
|
||||||
|
### Reporting Bugs
|
||||||
|
1. Check [Issues](../../issues) to see if the bug has already been reported.
|
||||||
|
2. If not, create a new Issue.
|
||||||
|
3. Use the "Bug Report" template.
|
||||||
|
4. Provide a **clear title and description**.
|
||||||
|
5. Include relevant code snippets, screenshots, or steps to reproduce the issue.
|
||||||
|
|
||||||
|
### Suggesting Enhancements
|
||||||
|
1. Check existing Issues to see if your idea has been suggested.
|
||||||
|
2. Create a new Issue using the "Feature Request" template.
|
||||||
|
3. Clearly describe the new feature and explain why it would be useful.
|
||||||
|
|
||||||
|
### Submitting Code Changes (Pull Requests)
|
||||||
|
1. **Fork** the repository on GitHub.
|
||||||
|
2. **Clone** your forked repository to your local machine.
|
||||||
|
3. Create a **new branch** for your feature or bug fix (`git checkout -b my-feature-branch`).
|
||||||
|
4. **Make your changes**. Ensure your code follows the project's style (see below).
|
||||||
|
5. **Commit your changes** with clear, descriptive commit messages.
|
||||||
|
6. **Push** your branch to your forked GitHub repository (`git push origin my-feature-branch`).
|
||||||
|
7. Open a **Pull Request** against the original StellarX repository's `main` branch.
|
||||||
|
|
||||||
|
## Code Style Guide
|
||||||
|
|
||||||
|
* Follow the existing code formatting and naming conventions in the project.
|
||||||
|
* Use meaningful names for variables, functions, and classes.
|
||||||
|
* Comment your code when necessary, especially for complex logic.
|
||||||
|
* Ensure your code compiles without warnings.
|
||||||
|
* Test your changes thoroughly.
|
||||||
|
* Use **4 spaces** for indentation (no tabs)
|
||||||
|
* Class names use **PascalCase** (e.g., `ClassName`)
|
||||||
|
* Functions and variables use **camelCase** (e.g., `functionName`, `variableName`)
|
||||||
|
* Constants use **UPPER_CASE** (e.g., `CONSTANT_VALUE`)
|
||||||
|
* Member variables use **m_** prefix (e.g., `m_memberVariable`)
|
||||||
|
* Use meaningful names for control properties, avoid abbreviations
|
||||||
|
* Add detailed comments for all public interfaces
|
||||||
|
* Follow RAII principles for resource management
|
||||||
|
|
||||||
|
## Example Code Style
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// Good Example
|
||||||
|
class MyControl : public Control {
|
||||||
|
public:
|
||||||
|
MyControl(int x, int y, int width, int height)
|
||||||
|
: Control(x, y, width, height), m_isActive(false) {}
|
||||||
|
|
||||||
|
void draw() override {
|
||||||
|
// Drawing logic
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_isActive;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bad Example
|
||||||
|
class my_control: public Control{
|
||||||
|
public:
|
||||||
|
my_control(int x,int y,int w,int h):Control(x,y,w,h),active(false){}
|
||||||
|
void Draw() override{
|
||||||
|
// Drawing logic
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool active;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
Please follow the project's directory structure:
|
||||||
|
|
||||||
|
- Header files go in the `include/StellarX/` directory
|
||||||
|
- Implementation files go in the `src/` directory
|
||||||
|
- Example code goes in the `examples/` directory
|
||||||
|
|
||||||
|
## Questions?
|
||||||
|
|
||||||
|
If you have any questions, feel free to open an Issue or contact the maintainers.
|
||||||
|
|
||||||
451
README.en.md
Normal file
451
README.en.md
Normal file
@@ -0,0 +1,451 @@
|
|||||||
|
# StellarX GUI Framework
|
||||||
|
|
||||||
|
[中文文档](README.md)
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[](https://github.com/Ysm-04/StellarX)
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
> **"Bound by Stars, Light as Dust"** — A native C++ GUI framework for Windows platform, featuring extreme lightweight and high modularity.
|
||||||
|
|
||||||
|
`StellarX` was born from resistance against "overly bloated" modern GUI frameworks. It rejects dependencies that often reach hundreds of MB, long compilation times, and steep learning curves, choosing to return to the essence: solving core desktop application development needs with the most concise code, clearest architecture, and highest efficiency.
|
||||||
|
|
||||||
|
It is a **pure teaching-level, tool-level framework** designed to help developers deeply understand GUI principles and quickly build lightweight Windows tools.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 📦 Project Structure & Design Philosophy
|
||||||
|
|
||||||
|
StellarX framework adopts classic **Object-Oriented** and **modular** design with a clear and standardized project structure:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
StellarX/
|
||||||
|
├── include/ # Header files directory
|
||||||
|
│ └── StellarX/ # Framework header files
|
||||||
|
│ ├── StellarX.h # Main include header - one-click import of entire framework
|
||||||
|
│ ├── CoreTypes.h # ★ Core ★ - Single source of truth for all enums and structs
|
||||||
|
│ ├── Control.h # Abstract base class - defines unified interface for all controls
|
||||||
|
│ ├── Button.h # Button control
|
||||||
|
│ ├── Window.h # Window management
|
||||||
|
│ ├── Label.h # Label control
|
||||||
|
│ ├── TextBox.h # Text box control
|
||||||
|
│ ├── Canvas.h # Canvas container
|
||||||
|
│ ├── Dialog.h # Dialog control (new in v2.0.0)
|
||||||
|
│ ├── MessageBox.h # Message box factory (new in v2.0.0)
|
||||||
|
│ └── Table.h # Table control
|
||||||
|
├── src/ # Source files directory
|
||||||
|
│ ├── Control.cpp
|
||||||
|
│ ├── Button.cpp
|
||||||
|
│ ├── Window.cpp
|
||||||
|
│ ├── Label.cpp
|
||||||
|
│ ├── TextBox.cpp
|
||||||
|
│ ├── Canvas.cpp
|
||||||
|
│ ├── Table.cpp
|
||||||
|
│ ├── Dialog.cpp # v2.0.0 new
|
||||||
|
│ └── MessageBox.cpp # v2.0.0 new
|
||||||
|
├── examples/ # Example code directory
|
||||||
|
│ └── demo.cpp # Basic demonstration
|
||||||
|
├── docs/ # Documentation directory
|
||||||
|
│ └── CODE_OF_CONDUCT.md # Code of Conduct
|
||||||
|
├── CMakeLists.txt # CMake build configuration
|
||||||
|
├── CONTRIBUTING.md # Contribution guide
|
||||||
|
├── CHANGELOG.md # Changelog
|
||||||
|
├── Doxyfile # Doxygen configuration
|
||||||
|
├── LICENSE # MIT License
|
||||||
|
└── README.md # Project description
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Design Philosophy:**
|
||||||
|
|
||||||
|
1. **Single Responsibility Principle (SRP)**: Each class/file is responsible for one thing only.
|
||||||
|
2. **Dependency Inversion Principle (DIP)**: High-level modules (like `Window`) don't depend on low-level modules (like `Button`), both depend on abstractions (`Control`).
|
||||||
|
3. **Open/Closed Principle (OCP)**: New controls can be easily extended by inheriting the `Control` base class without modifying existing code.
|
||||||
|
4. **Consistency**: All controls share unified `draw()` and `handleEvent()` interfaces.
|
||||||
|
|
||||||
|
## 🚀 Core Features
|
||||||
|
|
||||||
|
- **Extreme Lightweight**: Core library compiles to only ~1.2MB, with zero external dependencies. Generated applications are compact.
|
||||||
|
- **Clear Modular Architecture**: Uses `CoreTypes.h` to uniformly manage all types, eliminating duplicate definitions and greatly improving maintainability.
|
||||||
|
- **Native C++ Performance**: Built directly on EasyX and Win32 API, providing near-native execution efficiency with very low memory footprint (typically <10MB).
|
||||||
|
- **Complete Control System**: Button, Label, TextBox, Canvas, Table, Dialog, and MessageBox factory.
|
||||||
|
- **Highly Customizable**: From control colors, shapes (rectangle, rounded, circle, ellipse) to fill modes and font styles, all have detailed enum support for easy customization.
|
||||||
|
- **Simple & Intuitive API**: Uses classic object-oriented design, code as documentation, low learning curve.
|
||||||
|
- **Standard Project Structure**: Adopts standard include/src separation structure, supports CMake build, easy to integrate and use.
|
||||||
|
- **Enhanced Event System**: v2.0.0 introduces event consumption mechanism, all `handleEvent` methods return `bool` indicating whether event was consumed, supporting finer-grained event propagation control.
|
||||||
|
- **Dialog System**: New complete dialog support, including modal and non-modal dialogs, automatically handling background saving and restoration.
|
||||||
|
|
||||||
|
## ⚡ Quick Start (5 Minutes to Get Started)
|
||||||
|
|
||||||
|
> **🎯 Latest Version Download**
|
||||||
|
> Download pre-compiled library files and header files from [GitHub Releases](https://github.com/Ysm-04/StellarX/releases/latest) for quick integration into your project.
|
||||||
|
|
||||||
|
### Environment Requirements
|
||||||
|
|
||||||
|
- **OS**: Windows 10 or higher
|
||||||
|
- **Compiler**: C++17 supported compiler (e.g., **Visual Studio 2019+**)
|
||||||
|
- **Graphics Library**: [EasyX](https://easyx.cn/) (2022 version or higher, please select the version matching your compiler during installation)
|
||||||
|
- **Build Tool**: CMake 3.12+ (optional, recommended)
|
||||||
|
|
||||||
|
### Install EasyX
|
||||||
|
|
||||||
|
1. Visit [EasyX official website](https://easyx.cn/) to download the latest version
|
||||||
|
2. Run the installer, select the version matching your Visual Studio version
|
||||||
|
3. After installation, no additional configuration is needed, StellarX framework will automatically link EasyX
|
||||||
|
|
||||||
|
### Method 1: Using CMake Build (Recommended)
|
||||||
|
|
||||||
|
1. **Clone the project**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/Ysm-04/StellarX.git
|
||||||
|
cd StellarX
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Generate build system**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Compile the project**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake --build .
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Run the example**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./examples/Demo
|
||||||
|
```
|
||||||
|
|
||||||
|
### Method 2: Manual Integration into Existing Project
|
||||||
|
|
||||||
|
1. **Copy the include and src directories** to your project
|
||||||
|
2. **Configure include paths** to ensure the compiler can find the `include/StellarX/` directory
|
||||||
|
3. **Add all .cpp files** to your project for compilation
|
||||||
|
|
||||||
|
### Create Your First StellarX Application
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Just include this one header to use all features
|
||||||
|
#include "StellarX.h"
|
||||||
|
|
||||||
|
// Program entry point (use WinMain for better compatibility)
|
||||||
|
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
|
||||||
|
{
|
||||||
|
// 1. Create a 640x480 window with white background, titled "My App"
|
||||||
|
Window mainWindow(640, 480, 0, RGB(255, 255, 255), "My First StellarX App");
|
||||||
|
|
||||||
|
// 2. Create a button (managed with smart pointer)
|
||||||
|
auto myButton = std::make_unique<Button>(
|
||||||
|
250, 200, 140, 40, // x, y, width, height
|
||||||
|
"Click Me", // button text
|
||||||
|
StellarX::ButtonMode::NORMAL,
|
||||||
|
StellarX::ControlShape::ROUND_RECTANGLE
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. Set click event for the button (using Lambda expression)
|
||||||
|
myButton->setOnClickListener([&mainWindow]() {
|
||||||
|
// Use message box factory to create modal dialog
|
||||||
|
auto result = StellarX::MessageBox::ShowModal(
|
||||||
|
mainWindow,
|
||||||
|
"Welcome to StellarX GUI\r\nAuthor: Ysm-04",
|
||||||
|
"Greeting",
|
||||||
|
StellarX::MessageBoxType::OKCancel
|
||||||
|
);
|
||||||
|
// Handle dialog result
|
||||||
|
if (result == StellarX::MessageBoxResult::OK) {
|
||||||
|
// User clicked OK button
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 4. (Optional) Set button style
|
||||||
|
myButton->textStyle.nHeight = 20;
|
||||||
|
myButton->textStyle.color = RGB(0, 0, 128); // Dark blue text
|
||||||
|
myButton->setButtonBorder(RGB(0, 128, 255)); // Blue border
|
||||||
|
|
||||||
|
// 5. Add button to window
|
||||||
|
mainWindow.addControl(std::move(myButton));
|
||||||
|
|
||||||
|
// 6. Draw the window
|
||||||
|
mainWindow.draw();
|
||||||
|
|
||||||
|
// 7. Enter message loop, wait for user interaction
|
||||||
|
mainWindow.runEventLoop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
1. **Compile and run!** You'll see a window with a blue rounded button, clicking it will pop up a message box.
|
||||||
|
|
||||||
|
## 📚 Core Types Detailed Explanation (`CoreTypes.h`)
|
||||||
|
|
||||||
|
All visual and behavioral properties of the StellarX framework are controlled through the elegant enums and structs defined in `CoreTypes.h`.
|
||||||
|
|
||||||
|
### Enum Types (Enums)
|
||||||
|
|
||||||
|
| Enum Type | Description | Common Values |
|
||||||
|
| :--------------------- | :---------------------- | :----------------------------------------------------------- |
|
||||||
|
| **`ControlShape`** | Control geometric shape | `RECTANGLE`, `B_RECTANGLE`, `ROUND_RECTANGLE`, `CIRCLE`, `ELLIPSE`, etc. |
|
||||||
|
| **`ButtonMode`** | Button behavior mode | `NORMAL`, `TOGGLE`, `DISABLED` |
|
||||||
|
| **`TextBoxMode`** | Text box mode | `INPUT_MODE`, `READONLY_MODE` |
|
||||||
|
| **`FillMode`** | Graphics fill mode | `SOLID`, `NULL`, `HATCHED`, etc. |
|
||||||
|
| **`FillStyle`** | Pattern fill style | `HORIZONTAL`, `CROSS`, etc. |
|
||||||
|
| **`LineStyle`** | Border line style | `SOLID`, `DASH`, `DOT`, etc. |
|
||||||
|
| **`MessageBoxType`** | Message box type | `OK`, `OKCancel`, `YesNo`, `YesNoCancel`, `RetryCancel`, `AbortRetryIgnore` |
|
||||||
|
| **`MessageBoxResult`** | Message box result | `OK`, `Cancel`, `Yes`, `No`, `Abort`, `Retry`, `Ignore` |
|
||||||
|
|
||||||
|
### Structs (Structs)
|
||||||
|
|
||||||
|
| Struct | Description |
|
||||||
|
| :----------------- | :----------------------------------------------------------- |
|
||||||
|
| **`ControlText`** | Encapsulates all text style attributes, including font, size, color, bold, italic, underline, strikethrough, etc. |
|
||||||
|
| **`RouRectangle`** | Defines rounded rectangle corner ellipse dimensions, contains width and height properties. |
|
||||||
|
|
||||||
|
**Usage Example:**
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// Create a complex text style
|
||||||
|
StellarX::ControlText myStyle;
|
||||||
|
myStyle.nHeight = 25; // Font height
|
||||||
|
myStyle.lpszFace = _T("Microsoft YaHei"); // Font
|
||||||
|
myStyle.color = RGB(255, 0, 0); // Red color
|
||||||
|
myStyle.nWeight = FW_BOLD; // Bold
|
||||||
|
myStyle.bUnderline = true; // Underline
|
||||||
|
|
||||||
|
// Apply to controls
|
||||||
|
myLabel->textStyle = myStyle;
|
||||||
|
myButton->textStyle = myStyle;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧩 Complete Control Library
|
||||||
|
|
||||||
|
### 1. Basic Controls
|
||||||
|
|
||||||
|
| Control | Header File | Description | Key Features |
|
||||||
|
| :---------- | :---------- | :-------------------- | :----------------------------------------------------------- |
|
||||||
|
| **Button** | `Button.h` | Multi-function button | Supports multiple modes/shapes/states, hover/click colors, custom callbacks |
|
||||||
|
| **Label** | `Label.h` | Text label | Supports transparent/opaque background, custom font styles |
|
||||||
|
| **TextBox** | `TextBox.h` | Input box/Display box | Supports input and read-only modes, integrates EasyX's `InputBox` |
|
||||||
|
|
||||||
|
### 2. Container Controls
|
||||||
|
|
||||||
|
| Control | Header File | Description |
|
||||||
|
| :--------- | :---------- | :----------------------------------------------------------- |
|
||||||
|
| **Canvas** | `Canvas.h` | Container control, can serve as parent container for other controls, supports custom borders and background. |
|
||||||
|
| **Window** | `Window.h` | Top-level window, ultimate container for all controls, responsible for message loop and dispatching. |
|
||||||
|
|
||||||
|
### 3. Advanced Controls
|
||||||
|
|
||||||
|
| Control | Header File | Description | Key Features |
|
||||||
|
| :--------- | :---------- | :----------- | :----------------------------------------------------------- |
|
||||||
|
| **Table** | `Table.h` | Data table | **Framework highlight feature**, supports paginated display, custom headers and data, automatic column width calculation, page turn buttons. |
|
||||||
|
| **Dialog** | `Dialog.h` | Dialog class | Implements complete dialog functionality, supports multiple button combinations and asynchronous result callbacks. Automatically handles layout, background save/restore and lifecycle management. |
|
||||||
|
|
||||||
|
**Table Control Example:**
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// Create a table
|
||||||
|
auto myTable = std::make_unique<Table>(50, 50);
|
||||||
|
|
||||||
|
// Set headers
|
||||||
|
myTable->setHeaders({ "ID", "Name", "Age", "Occupation" });
|
||||||
|
|
||||||
|
// Add data rows
|
||||||
|
myTable->setData({ "1", "Zhang San", "25", "Engineer" });
|
||||||
|
myTable->setData({ "2", "Li Si", "30", "Designer" });
|
||||||
|
myTable->setData({ "3", "Wang Wu", "28", "Product Manager" });
|
||||||
|
|
||||||
|
// Set rows per page
|
||||||
|
myTable->setRowsPerPage(2);
|
||||||
|
|
||||||
|
// Set table style
|
||||||
|
myTable->textStyle.nHeight = 16;
|
||||||
|
myTable->setTableBorder(RGB(50, 50, 50));
|
||||||
|
myTable->setTableBk(RGB(240, 240, 240));
|
||||||
|
|
||||||
|
// Add to window
|
||||||
|
mainWindow.addControl(std::move(myTable));
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Static Factory Class
|
||||||
|
|
||||||
|
| Control | Header File | Description | Key Features |
|
||||||
|
| :------------- | :------------- | :------------------- | :----------------------------------------------------------- |
|
||||||
|
| **MessageBox** | `MessageBox.h` | Dialog factory calls | Static method calls, no instantiation needed, automatically handles modal and non-modal logic differences, integrated into window's dialog management system, provides deduplication mechanism to prevent duplicate dialogs |
|
||||||
|
|
||||||
|
**MessageBox Usage Example:**
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// Modal message box (blocks until closed)
|
||||||
|
auto result = StellarX::MessageBox::ShowModal(
|
||||||
|
mainWindow,
|
||||||
|
"Confirm to perform this operation?",
|
||||||
|
"Confirmation",
|
||||||
|
StellarX::MessageBoxType::YesNo
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == StellarX::MessageBoxResult::Yes)
|
||||||
|
{
|
||||||
|
// User selected "Yes"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-modal message box (asynchronous callback)
|
||||||
|
StellarX::MessageBox::ShowAsync(
|
||||||
|
mainWindow,
|
||||||
|
"Operation completed",
|
||||||
|
"Notification",
|
||||||
|
StellarX::MessageBoxType::OK,
|
||||||
|
[](StellarX::MessageBoxResult result) {
|
||||||
|
// Asynchronously handle result
|
||||||
|
}
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
- **Register Viewer (≈450 lines)** — An interactive 32-bit register visualization tool implemented based on StellarX (supports bit inversion, left/right shift, hex/decimal conversion, signed/unsigned toggle, binary grouping display).
|
||||||
|
Path: `examples/register-viewer/`
|
||||||
|
|
||||||
|
## 🔧 Advanced Topics & Best Practices
|
||||||
|
|
||||||
|
### 1. Custom Controls
|
||||||
|
|
||||||
|
You can create custom controls by inheriting from the `Control` base class. Just implement the two pure virtual functions `draw()` and `handleEvent()`.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
class MyCustomControl : public Control {
|
||||||
|
public:
|
||||||
|
MyCustomControl(int x, int y) : Control(x, y, 100, 100) {}
|
||||||
|
|
||||||
|
void draw() override {
|
||||||
|
saveStyle();
|
||||||
|
// Your custom drawing logic
|
||||||
|
setfillcolor(RGB(255, 100, 100));
|
||||||
|
fillrectangle(x, y, x + width, y + height);
|
||||||
|
restoreStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handleEvent(const ExMessage& msg) override {
|
||||||
|
// Your custom event handling logic
|
||||||
|
if (msg.message == WM_LBUTTONDOWN &&
|
||||||
|
msg.x > x && msg.x < x + width &&
|
||||||
|
msg.y > y && msg.y < y + height) {
|
||||||
|
// Handle click
|
||||||
|
return true; // Event consumed
|
||||||
|
}
|
||||||
|
return false; // Event not consumed
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsVisible() const override { return true; }
|
||||||
|
bool model() const override { return false; }
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Layout Management
|
||||||
|
|
||||||
|
Current version of StellarX primarily uses **absolute positioning**. For simple layouts, you can achieve this by calculating coordinates. For complex layouts, consider:
|
||||||
|
|
||||||
|
- Nesting controls in `Canvas` to achieve relative positioning.
|
||||||
|
- Implementing simple flow layout or grid layout managers yourself.
|
||||||
|
|
||||||
|
### 3. Performance Optimization
|
||||||
|
|
||||||
|
- **Dirty Rectangle Rendering**: Implemented internally in the framework, controls set `dirty=true` when state changes, only redraw when necessary.
|
||||||
|
- **Image Resources**: Use `IMAGE` objects to load images, then reuse them to avoid multiple loads.
|
||||||
|
- **Reduce Operations in Loops**: Avoid heavy calculations in `draw()` and `handleEvent()`.
|
||||||
|
- **Event Consumption Mechanism**: Use event consumption return values appropriately to avoid unnecessary event propagation.
|
||||||
|
|
||||||
|
### 4. Dialog Usage Tips
|
||||||
|
|
||||||
|
- **Modal Dialogs**: Use `ShowModal` method, blocks current thread until dialog closes, suitable for important operations requiring user confirmation.
|
||||||
|
- **Non-modal Dialogs**: Use `ShowAsync` method, doesn't block main thread, suitable for informational prompts or background tasks.
|
||||||
|
- **Dialog Deduplication**: Framework has built-in non-modal dialog deduplication mechanism to prevent multiple dialogs for the same message from appearing simultaneously.
|
||||||
|
|
||||||
|
## ⚠️ Important Limitations & Suitable Scenarios
|
||||||
|
|
||||||
|
**StellarX framework's design goals are lightness, clarity, and teaching value, therefore it explicitly is NOT suitable for the following scenarios:**
|
||||||
|
|
||||||
|
- **High-performance games or complex animations**: Rendering is based on EasyX's CPU software rendering, performance is limited.
|
||||||
|
- **Applications requiring high DPI scaling**: Limited support for high DPI displays, interface may not display correctly.
|
||||||
|
- **Applications requiring accessibility features**: No support for screen readers and other assistive technologies.
|
||||||
|
- **Cross-platform applications**: Deeply dependent on Windows API and EasyX, cannot run directly on Linux/macOS.
|
||||||
|
- **Complex commercial software frontends**: Lacks advanced controls (like tree views, rich text boxes, tabs, advanced lists) and mature automatic layout managers.
|
||||||
|
|
||||||
|
**If you need to develop the aforementioned types of applications, please consider the following mature solutions:**
|
||||||
|
|
||||||
|
- **Qt**: Extremely powerful, cross-platform, suitable for large commercial applications.
|
||||||
|
- **wxWidgets**: Native appearance, cross-platform.
|
||||||
|
- **Dear ImGui**: Immediate mode GUI, very suitable for tools and debug interfaces.
|
||||||
|
- **Web Technology Stack (Electron/CEF)**: Suitable for scenarios requiring web technologies.
|
||||||
|
|
||||||
|
## 📜 License
|
||||||
|
|
||||||
|
This project uses the **MIT License**.
|
||||||
|
|
||||||
|
You are free to:
|
||||||
|
|
||||||
|
- Use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the framework.
|
||||||
|
- Use it for private or commercial projects.
|
||||||
|
|
||||||
|
The only requirement is:
|
||||||
|
|
||||||
|
- Please retain the original copyright notice in your projects.
|
||||||
|
|
||||||
|
See the [LICENSE](https://license/) file in the project root directory for details.
|
||||||
|
|
||||||
|
## 👥 Contribution Guide
|
||||||
|
|
||||||
|
We welcome all forms of contributions! If you want to contribute to the StellarX framework, please read the following guidelines:
|
||||||
|
|
||||||
|
1. **Code Style**: Please follow the existing Google C++ style guide (use spaces for indentation, braces on new lines, etc.).
|
||||||
|
2. **New Features**: Must provide **example code** and update relevant parts of this README document.
|
||||||
|
3. **Submitting PRs**: Please ensure your code is tested before submission and clearly describe your changes and motivation.
|
||||||
|
4. **Issue Reporting**: If you find a bug or have new ideas, welcome to submit Issues on GitHub.
|
||||||
|
|
||||||
|
Detailed contribution guide please refer to [CONTRIBUTING.md](CONTRIBUTING.en.md).
|
||||||
|
|
||||||
|
## 🙏 Acknowledgements
|
||||||
|
|
||||||
|
- Thanks to [EasyX Graphics Library](https://easyx.cn/) for providing the simple and easy-to-use graphics foundation for this project, making C++ GUI programming education possible.
|
||||||
|
- Thanks to all developers pursuing the **concise, efficient, clear** coding philosophy, you are the inspiration for StellarX's birth.
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
**Star Ocean Vast, Code as Boat.**
|
||||||
|
|
||||||
|
May `StellarX` become a reliable cornerstone for your exploration of the GUI world, whether for learning, teaching, or creating practical tools.
|
||||||
|
|
||||||
|
## 📞 Support & Feedback
|
||||||
|
|
||||||
|
If you encounter problems during use or have any suggestions:
|
||||||
|
|
||||||
|
1. Check [Example Code](examples/) for usage reference
|
||||||
|
2. Check [Changelog](CHANGELOG.en.md) to learn about latest changes
|
||||||
|
3. Submit Issues on GitHub repository to report problems
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
*StellarX Framework - Light as Dust, Bound by Stars*
|
||||||
|
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
# 星垣 (StellarX) GUI Framework
|
# 星垣 (StellarX) GUI Framework
|
||||||
|
|
||||||
|
[English document](README.en.md)
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
[](https://github.com/Ysm-04/StellarX)
|
[](https://github.com/Ysm-04/StellarX)
|
||||||
@@ -321,7 +325,9 @@ StellarX::MessageBox::ShowAsync(
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 示例
|
||||||
|
- **寄存器查看器 (≈450 行)** — 一个基于 StellarX 实现的交互式 32 位寄存器可视化工具(支持位取反、左/右移、十六进制/十进制转换、带有符号/无符号切换、二进制分组显示)。
|
||||||
|
路径:`examples/register-viewer/`
|
||||||
|
|
||||||
## 🔧 高级主题与最佳实践
|
## 🔧 高级主题与最佳实践
|
||||||
|
|
||||||
|
|||||||
25
docs/CODE_OF_CONDUCT.en.md
Normal file
25
docs/CODE_OF_CONDUCT.en.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and maintainers pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
|
* Being considerate and respectful of others
|
||||||
|
* Respecting different viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project maintainers. All complaints will be reviewed and investigated promptly and fairly, and will result in a response that is deemed necessary and appropriate to the circumstances.
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
|
||||||
17
examples/register-viewer/README.md
Normal file
17
examples/register-viewer/README.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Register Viewer (StellarX example)
|
||||||
|
|
||||||
|
**A 32-bit register visualizer built with StellarX** (Windows + EasyX).
|
||||||
|
Features:
|
||||||
|
- 32 toggle bits (MSB→LSB = 31..0)
|
||||||
|
- Range invert, logical left/right shift
|
||||||
|
- Hex/Decimal display with signed/unsigned toggle
|
||||||
|
- Grouped binary view with "last/current" snapshots
|
||||||
|
- One-click set all 0 / all 1
|
||||||
|
|
||||||
|
## Build & Run
|
||||||
|
1. Ensure StellarX and EasyX are in your include/lib paths.
|
||||||
|
2. Build as a normal C++ Win32 desktop app (e.g., VS 2019+).
|
||||||
|
3. Run the executable.
|
||||||
|
|
||||||
|
This example demonstrates StellarX APIs with a single `main.cpp` (~450 LOC):
|
||||||
|
`Window / Canvas / Button / Label / TextBox` + simple event callbacks.
|
||||||
462
examples/register-viewer/main.cpp
Normal file
462
examples/register-viewer/main.cpp
Normal file
@@ -0,0 +1,462 @@
|
|||||||
|
// 本工具基于 StellarX 构建,轻量级的 Windows GUI 框架。
|
||||||
|
#include"StellarX.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include<iomanip>
|
||||||
|
#include<array>
|
||||||
|
|
||||||
|
auto blackColor = RGB(202, 255, 255);
|
||||||
|
char initData[33] = "00000000000000000000000000000000";//初始数据
|
||||||
|
bool gSigned = false; //是否为有符号数
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Window mainWindow(700,500,NULL,RGB(255,255,255), "寄存器查看工具 V1.0——我在人间做废物 (同类工具定制:3150131407(Q / V))");
|
||||||
|
|
||||||
|
//选择区控件
|
||||||
|
auto selectionAreaLabel = std::make_unique<Label>(18, 0,"32位选择区");
|
||||||
|
selectionAreaLabel->setTextdisap(true);
|
||||||
|
std::vector<std::unique_ptr<Label>>selectionAreaButtonLabel;
|
||||||
|
std::vector<std::unique_ptr<Button>>selectionAreaButton;
|
||||||
|
std::vector<Button*>selectionAreaButton_ptr;
|
||||||
|
auto selectionArea = std::make_unique <Canvas>(10, 10, 680, 150);
|
||||||
|
|
||||||
|
selectionArea->setCanvasBkColor(blackColor);
|
||||||
|
selectionArea->setShape(StellarX::ControlShape::B_ROUND_RECTANGLE);
|
||||||
|
|
||||||
|
for (int y = 0; y < 2; y ++)
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
for (int x = 0; x <16; x++)
|
||||||
|
{
|
||||||
|
if (0 == y)
|
||||||
|
{
|
||||||
|
selectionAreaButtonLabel.push_back(std::make_unique<Label>(x * 35 + 40 + 28 * (x / 4), 26, "", RGB(208, 208, 208)));
|
||||||
|
os << std::setw(2) << std::setfill('0') << 31 - x;
|
||||||
|
selectionAreaButtonLabel.back()->setText(os.str());
|
||||||
|
selectionAreaButtonLabel.back()->setTextdisap(true);
|
||||||
|
|
||||||
|
selectionAreaButton.push_back(
|
||||||
|
std::make_unique<Button>(x * 35 + 42 + 28 * (x / 4), 58,20,32,"0",
|
||||||
|
blackColor,RGB(171, 196, 220),StellarX::ButtonMode::TOGGLE));
|
||||||
|
selectionAreaButton.back()->textStyle.color = RGB(226, 116, 152);
|
||||||
|
selectionAreaButton.back()->setButtonShape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
selectionAreaButton_ptr.push_back(selectionAreaButton.back().get());
|
||||||
|
int k = 32 - x - 1;
|
||||||
|
//选择区按钮被点击后在二进制0和1之间切换,并更新initData
|
||||||
|
selectionAreaButton_ptr.back()->setOnToggleOnListener([k, btn = selectionAreaButton_ptr.back()]()
|
||||||
|
{
|
||||||
|
btn->setButtonText("1");
|
||||||
|
initData[k] = '1';
|
||||||
|
});
|
||||||
|
selectionAreaButton_ptr.back()->setOnToggleOffListener([k, btn = selectionAreaButton_ptr.back()]()
|
||||||
|
{
|
||||||
|
btn->setButtonText("0");
|
||||||
|
initData[k] = '0';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selectionAreaButtonLabel.push_back(std::make_unique<Label>(x * 35 + 40 + 28 * (x / 4), 90, "", RGB(208, 208, 208)));
|
||||||
|
os << std::setw(2) << std::setfill('0') << 15-x;
|
||||||
|
selectionAreaButtonLabel.back()->setText(os.str());
|
||||||
|
selectionAreaButtonLabel.back()->setTextdisap(true);
|
||||||
|
|
||||||
|
selectionAreaButton.push_back(
|
||||||
|
std::make_unique<Button>(x * 35 + 42 + 28 * (x / 4), 120, 20, 32, "0",
|
||||||
|
blackColor, RGB(171, 196, 220), StellarX::ButtonMode::TOGGLE));
|
||||||
|
selectionAreaButton.back()->textStyle.color = RGB(226, 116, 152);
|
||||||
|
selectionAreaButton.back()->setButtonShape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
selectionAreaButton_ptr.push_back(selectionAreaButton.back().get());
|
||||||
|
int k =15 - x;
|
||||||
|
selectionAreaButton.back()->setOnToggleOnListener([k,btn = selectionAreaButton_ptr.back()]()
|
||||||
|
{
|
||||||
|
btn->setButtonText("1");
|
||||||
|
initData[k] = '1';
|
||||||
|
});
|
||||||
|
selectionAreaButton.back()->setOnToggleOffListener([k, btn = selectionAreaButton_ptr.back()]()
|
||||||
|
{
|
||||||
|
btn->setButtonText("0");
|
||||||
|
initData[k] = '0';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
os.str("");
|
||||||
|
os.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectionArea->addControl(std::move(selectionAreaLabel));
|
||||||
|
for (auto& s : selectionAreaButton)
|
||||||
|
selectionArea->addControl(std::move(s));
|
||||||
|
for (auto& s : selectionAreaButtonLabel)
|
||||||
|
selectionArea->addControl(std::move(s));
|
||||||
|
//功能区控件
|
||||||
|
//功能区总容器
|
||||||
|
auto function = std::make_unique<Canvas>(0, 0, 0, 0);
|
||||||
|
function->setCanvasfillMode(StellarX::FillMode::Null);
|
||||||
|
|
||||||
|
auto bitInvert = std::make_unique<Canvas>(10,170,220,70);
|
||||||
|
auto leftShift = std::make_unique<Canvas>(240, 170, 220, 70);
|
||||||
|
auto rightShift = std::make_unique<Canvas>(470, 170, 220, 70);
|
||||||
|
bitInvert->setCanvasBkColor(blackColor);
|
||||||
|
bitInvert->setShape(StellarX::ControlShape::B_ROUND_RECTANGLE);
|
||||||
|
leftShift->setCanvasBkColor(blackColor);
|
||||||
|
leftShift->setShape(StellarX::ControlShape::B_ROUND_RECTANGLE);
|
||||||
|
rightShift->setCanvasBkColor(blackColor);
|
||||||
|
rightShift->setShape(StellarX::ControlShape::B_ROUND_RECTANGLE);
|
||||||
|
|
||||||
|
|
||||||
|
auto bitInvertLabel = std::make_unique<Label>(18,160,"位取反");
|
||||||
|
bitInvertLabel->setTextdisap(true);
|
||||||
|
auto leftShiftLabel = std::make_unique<Label>(248, 160, "左移位");
|
||||||
|
leftShiftLabel->setTextdisap(true);
|
||||||
|
auto rightShiftLabel = std::make_unique<Label>(478, 160, "右移位");
|
||||||
|
rightShiftLabel->setTextdisap(true);
|
||||||
|
|
||||||
|
// ====== 公用小工具======
|
||||||
|
auto clamp = [](int v, int lo, int hi) { return v < lo ? lo : (v > hi ? hi : v); };
|
||||||
|
auto toInt = [](const std::string& s, int def = 0) {
|
||||||
|
try { return std::stoi(s); }
|
||||||
|
catch (...) { return def; }
|
||||||
|
};
|
||||||
|
// bit号(31..0) -> selectionAreaButton下标(0..31)
|
||||||
|
auto vecIndexFromBit = [](int bit) { return 31 - bit; };
|
||||||
|
|
||||||
|
// 读取当前32位点击态
|
||||||
|
auto snapshotBits = [&]() {
|
||||||
|
std::array<bool, 32> a{};
|
||||||
|
for (int b = 0; b < 32; ++b)
|
||||||
|
a[b] = selectionAreaButton_ptr[vecIndexFromBit(b)]->isClicked();
|
||||||
|
return a;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 应用目标态:仅当不同才 setButtonClick
|
||||||
|
auto applyBits = [&](const std::array<bool, 32>& a) {
|
||||||
|
for (int b = 0; b < 32; ++b) {
|
||||||
|
auto btn = selectionAreaButton_ptr[vecIndexFromBit(b)];
|
||||||
|
if (btn->isClicked() != a[b]) btn->setButtonClick(a[b]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//取反区控件
|
||||||
|
std::array<std::unique_ptr<Label>, 4> bitInvertFunctionLabel;
|
||||||
|
bitInvertFunctionLabel[0] = std::make_unique<Label>(35, 180, "低位");
|
||||||
|
bitInvertFunctionLabel[1] = std::make_unique<Label>(90, 180, "高位");
|
||||||
|
bitInvertFunctionLabel[2] = std::make_unique<Label>(15, 198, "从");
|
||||||
|
bitInvertFunctionLabel[3] = std::make_unique<Label>(75, 198, "到");
|
||||||
|
|
||||||
|
std::array<std::unique_ptr<TextBox>, 2> bitInvertFunctionTextBox;
|
||||||
|
bitInvertFunctionTextBox[0] = std::make_unique<TextBox>(35, 203, 35, 30, "0");
|
||||||
|
bitInvertFunctionTextBox[1] = std::make_unique<TextBox>(95, 203, 35, 30, "0");
|
||||||
|
auto invL = bitInvertFunctionTextBox[0].get();
|
||||||
|
auto invH = bitInvertFunctionTextBox[1].get();
|
||||||
|
auto bitInvertFunctionButton = std::make_unique<Button>(150,195, 70, 35, "位取反",
|
||||||
|
blackColor, RGB(171, 196, 220));
|
||||||
|
bitInvertFunctionButton->textStyle.color = RGB(226, 116, 152);
|
||||||
|
bitInvertFunctionButton->setButtonShape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
auto bitInvertFunctionButton_ptr = bitInvertFunctionButton.get();
|
||||||
|
|
||||||
|
bitInvert->addControl(std::move(bitInvertFunctionButton));
|
||||||
|
bitInvert->addControl(std::move(bitInvertLabel));
|
||||||
|
for (auto& b : bitInvertFunctionTextBox)
|
||||||
|
{
|
||||||
|
b->setMaxCharLen(3);
|
||||||
|
b->textStyle.color = RGB(226, 116, 152);
|
||||||
|
b->setTextBoxBk(RGB(244, 234, 142));
|
||||||
|
b->setTextBoxshape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
bitInvert->addControl(std::move(b));
|
||||||
|
}
|
||||||
|
for (auto& b : bitInvertFunctionLabel)
|
||||||
|
{
|
||||||
|
b->setTextdisap(true);
|
||||||
|
bitInvert->addControl(std::move(b));
|
||||||
|
}
|
||||||
|
//左移控件
|
||||||
|
auto leftShiftFunctionLabel = std::make_unique<Label>(435, 198, "位");
|
||||||
|
leftShiftFunctionLabel->setTextdisap(true);
|
||||||
|
|
||||||
|
auto leftShiftFunctionTextBox = std::make_unique<TextBox>(325, 195, 100, 30, "0");
|
||||||
|
leftShiftFunctionTextBox->setMaxCharLen(3);
|
||||||
|
leftShiftFunctionTextBox->textStyle.color = RGB(226, 116, 152);
|
||||||
|
leftShiftFunctionTextBox->setTextBoxBk(RGB(244, 234, 142));
|
||||||
|
leftShiftFunctionTextBox->setTextBoxshape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
auto shlBox = leftShiftFunctionTextBox.get();
|
||||||
|
auto leftShiftFunctionButton = std::make_unique<Button>(250, 195, 60, 30, "左移",
|
||||||
|
blackColor, RGB(171, 196, 220));
|
||||||
|
leftShiftFunctionButton->textStyle.color = RGB(226, 116, 152);
|
||||||
|
leftShiftFunctionButton->setButtonShape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
auto leftShiftFunctionButton_ptr = leftShiftFunctionButton.get();
|
||||||
|
|
||||||
|
|
||||||
|
leftShift->addControl(std::move(leftShiftFunctionButton));
|
||||||
|
leftShift->addControl(std::move(leftShiftFunctionTextBox));
|
||||||
|
|
||||||
|
leftShift->addControl(std::move(leftShiftLabel));
|
||||||
|
leftShift->addControl(std::move(leftShiftFunctionLabel));
|
||||||
|
|
||||||
|
//右移控件
|
||||||
|
auto rightShiftFunctionLabel = std::make_unique<Label>(665, 198, "位");
|
||||||
|
rightShiftFunctionLabel->setTextdisap(true);
|
||||||
|
auto rightShiftFunctionTextBox = std::make_unique<TextBox>(555, 195, 100, 30, "0");
|
||||||
|
rightShiftFunctionTextBox->setMaxCharLen(3);
|
||||||
|
rightShiftFunctionTextBox->textStyle.color = RGB(226, 116, 152);
|
||||||
|
rightShiftFunctionTextBox->setTextBoxBk(RGB(244, 234, 142));
|
||||||
|
rightShiftFunctionTextBox->setTextBoxshape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
auto shrBox = rightShiftFunctionTextBox.get();
|
||||||
|
|
||||||
|
auto rightShiftFunctionButton = std::make_unique<Button>(480, 195, 60, 30, "右移",
|
||||||
|
blackColor, RGB(171, 196, 220));
|
||||||
|
rightShiftFunctionButton->textStyle.color = RGB(226, 116, 152);
|
||||||
|
rightShiftFunctionButton->setButtonShape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
auto rightShiftFunctionButton_ptr = rightShiftFunctionButton.get();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
rightShift->addControl(std::move(rightShiftFunctionButton));
|
||||||
|
|
||||||
|
rightShift->addControl(std::move(rightShiftFunctionTextBox));
|
||||||
|
rightShift->addControl(std::move(rightShiftLabel));
|
||||||
|
rightShift->addControl(std::move(rightShiftFunctionLabel));
|
||||||
|
|
||||||
|
function->addControl(std::move(bitInvert));
|
||||||
|
function->addControl(std::move(leftShift));
|
||||||
|
function->addControl(std::move(rightShift));
|
||||||
|
|
||||||
|
//显示区控件
|
||||||
|
//数值显示
|
||||||
|
auto NumericalDisplayArea = std::make_unique<Canvas>(10, 255, 680, 70);
|
||||||
|
NumericalDisplayArea->setCanvasBkColor(blackColor);
|
||||||
|
NumericalDisplayArea->setShape(StellarX::ControlShape::B_ROUND_RECTANGLE);
|
||||||
|
|
||||||
|
std::array<std::unique_ptr<Label>, 3> NumericalDisplayAreaLabel;
|
||||||
|
NumericalDisplayAreaLabel[0] = std::make_unique<Label>(18, 245, "数值显示区");
|
||||||
|
NumericalDisplayAreaLabel[1] = std::make_unique<Label>(20, 278, "十六进制");
|
||||||
|
NumericalDisplayAreaLabel[2] = std::make_unique<Label>(330, 278, "十进制");
|
||||||
|
|
||||||
|
std::array<std::unique_ptr<TextBox>, 2> NumericalDisplayAreaTextBox;
|
||||||
|
NumericalDisplayAreaTextBox[0] = std::make_unique<TextBox>(110, 275, 200, 30, "0");
|
||||||
|
NumericalDisplayAreaTextBox[1] = std::make_unique<TextBox>(400, 275, 200, 30, "0");
|
||||||
|
auto hex = NumericalDisplayAreaTextBox[0].get();
|
||||||
|
auto dec = NumericalDisplayAreaTextBox[1].get();
|
||||||
|
|
||||||
|
|
||||||
|
for (auto& b : NumericalDisplayAreaLabel)
|
||||||
|
{
|
||||||
|
b->setTextdisap(true);
|
||||||
|
NumericalDisplayArea->addControl(std::move(b));
|
||||||
|
}
|
||||||
|
for (auto& b : NumericalDisplayAreaTextBox)
|
||||||
|
{
|
||||||
|
b->setMaxCharLen(11);
|
||||||
|
b->textStyle.color = RGB(255, 69, 0);
|
||||||
|
b->setTextBoxBk(RGB(141, 141, 141));
|
||||||
|
b->setTextBoxshape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
b->setMode(StellarX::TextBoxmode::READONLY_MODE);
|
||||||
|
NumericalDisplayArea->addControl(std::move(b));
|
||||||
|
}
|
||||||
|
//二进制显示
|
||||||
|
auto BinaryDisplayArea = std::make_unique<Canvas>(10, 335, 680, 110);
|
||||||
|
BinaryDisplayArea->setCanvasBkColor(blackColor);
|
||||||
|
BinaryDisplayArea->setShape(StellarX::ControlShape::B_ROUND_RECTANGLE);
|
||||||
|
|
||||||
|
std::array<std::unique_ptr<Label>, 3> BinaryDisplayAreaLabel;
|
||||||
|
BinaryDisplayAreaLabel[0] = std::make_unique<Label>(18, 325, "二进制显示区");
|
||||||
|
BinaryDisplayAreaLabel[1] = std::make_unique<Label>(35, 353, "上次值");
|
||||||
|
BinaryDisplayAreaLabel[2] = std::make_unique<Label>(35, 400, "本次值");
|
||||||
|
|
||||||
|
std::array<std::unique_ptr<TextBox>, 2> BinaryDisplayAreaTextBox;
|
||||||
|
BinaryDisplayAreaTextBox[0] = std::make_unique<TextBox>(110, 350, 520, 30, "0000_0000_0000_0000_0000_0000_0000_0000");
|
||||||
|
BinaryDisplayAreaTextBox[1] = std::make_unique<TextBox>(110, 400, 520, 30, "0000_0000_0000_0000_0000_0000_0000_0000");
|
||||||
|
auto Last = BinaryDisplayAreaTextBox[0].get();
|
||||||
|
auto This = BinaryDisplayAreaTextBox[1].get();
|
||||||
|
|
||||||
|
|
||||||
|
for (auto& b : BinaryDisplayAreaLabel)
|
||||||
|
{
|
||||||
|
b->setTextdisap(true);
|
||||||
|
BinaryDisplayArea->addControl(std::move(b));
|
||||||
|
}
|
||||||
|
for (auto& b : BinaryDisplayAreaTextBox)
|
||||||
|
{
|
||||||
|
b->setMaxCharLen(40);
|
||||||
|
b->textStyle.color = RGB(255, 69, 0);
|
||||||
|
b->setTextBoxBk(RGB(141, 141, 141));
|
||||||
|
b->setTextBoxshape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
b->setMode(StellarX::TextBoxmode::READONLY_MODE);
|
||||||
|
BinaryDisplayArea->addControl(std::move(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 由位图 bits 生成数值
|
||||||
|
auto valueFromBits = [](const std::array<bool, 32>& bits) -> uint32_t {
|
||||||
|
uint32_t v = 0;
|
||||||
|
for (int b = 0; b < 32; ++b) if (bits[b]) v |= (1u << b);
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 由位图 bits 生成 "0000_0000_..._0000"(MSB→LSB:31..0)
|
||||||
|
auto binaryGroupedFromBits = [](const std::array<bool, 32>& bits) -> std::string {
|
||||||
|
std::string s; s.reserve(39);
|
||||||
|
for (int b = 31; b >= 0; --b) {
|
||||||
|
s.push_back(bits[b] ? '1' : '0');
|
||||||
|
if (b % 4 == 0 && b != 0) s.push_back('_');
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 用“目标位图 bits”刷新显示区
|
||||||
|
auto refreshDisplaysWithBits = [&](const std::string& prevThis,
|
||||||
|
const std::array<bool, 32>& bits,
|
||||||
|
TextBox* hex, TextBox* dec, TextBox* Last, TextBox* This)
|
||||||
|
{
|
||||||
|
const uint32_t val = valueFromBits(bits);
|
||||||
|
const int32_t s = static_cast<int32_t>(val);
|
||||||
|
char hexbuf[16];
|
||||||
|
std::snprintf(hexbuf, sizeof(hexbuf), "%08X", val);
|
||||||
|
|
||||||
|
hex->setText(hexbuf); // HEX(大写8位)
|
||||||
|
dec->setText(gSigned ? std::to_string(s) : std::to_string(val)); // DEC
|
||||||
|
Last->setText(prevThis); // 上次值 ← 刷新前的本次值
|
||||||
|
This->setText(binaryGroupedFromBits(bits)); // 本次值 ← 由“目标位图”生成
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bitInvertFunctionButton_ptr->setOnClickListener([=, &snapshotBits, &applyBits, &refreshDisplaysWithBits]() {
|
||||||
|
const std::string prevThis = This->getText();
|
||||||
|
|
||||||
|
int L = clamp(toInt(invL->getText(), 0), 0, 31);
|
||||||
|
int H = clamp(toInt(invH->getText(), 0), 0, 31);
|
||||||
|
if (L > H) std::swap(L, H);
|
||||||
|
|
||||||
|
auto cur = snapshotBits();
|
||||||
|
for (int b = L; b <= H; ++b) cur[b] = !cur[b];
|
||||||
|
|
||||||
|
applyBits(cur); // 只改按钮点击态(触发位按钮自回调)
|
||||||
|
refreshDisplaysWithBits(prevThis, cur, hex, dec, Last, This);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
leftShiftFunctionButton_ptr->setOnClickListener([=, &snapshotBits, &applyBits, &refreshDisplaysWithBits]() {
|
||||||
|
const std::string prevThis = This->getText();
|
||||||
|
|
||||||
|
int n = clamp(toInt(shlBox->getText(), 0), 0, 31);
|
||||||
|
auto cur = snapshotBits();
|
||||||
|
std::array<bool, 32> nxt{}; // 默认全 0
|
||||||
|
|
||||||
|
// 逻辑左移:高位丢弃、低位补 0
|
||||||
|
for (int b = 31; b >= 0; --b) nxt[b] = (b >= n) ? cur[b - n] : false;
|
||||||
|
|
||||||
|
applyBits(nxt);
|
||||||
|
refreshDisplaysWithBits(prevThis, nxt, hex, dec, Last, This);
|
||||||
|
});
|
||||||
|
|
||||||
|
rightShiftFunctionButton_ptr->setOnClickListener([=, &snapshotBits, &applyBits, &refreshDisplaysWithBits]() {
|
||||||
|
const std::string prevThis = This->getText();
|
||||||
|
|
||||||
|
int n = clamp(toInt(shrBox->getText(), 0), 0, 31);
|
||||||
|
auto cur = snapshotBits();
|
||||||
|
std::array<bool, 32> nxt{};
|
||||||
|
|
||||||
|
// 逻辑右移:低位丢弃、高位补 0
|
||||||
|
for (int b = 0; b < 32; ++b) nxt[b] = (b + n <= 31) ? cur[b + n] : false;
|
||||||
|
|
||||||
|
applyBits(nxt);
|
||||||
|
refreshDisplaysWithBits(prevThis, nxt, hex, dec, Last, This);
|
||||||
|
});
|
||||||
|
|
||||||
|
//配置区控件clearrectangle(10, 440, 690, 490);
|
||||||
|
auto configuration = std::make_unique<Canvas>(10, 455, 680, 40);
|
||||||
|
configuration->setCanvasBkColor(blackColor);
|
||||||
|
configuration->setShape(StellarX::ControlShape::B_ROUND_RECTANGLE);
|
||||||
|
|
||||||
|
auto configurationLabel = std::make_unique<Label>(20, 445, "配置区");
|
||||||
|
configurationLabel->setTextdisap(true);
|
||||||
|
|
||||||
|
std::array<std::unique_ptr<Button>,2> configurationButton;
|
||||||
|
configurationButton[0] = std::make_unique<Button>(450, 465, 80, 20, "一键置0",
|
||||||
|
blackColor, RGB(171, 196, 220));
|
||||||
|
configurationButton[0]->textStyle.color = RGB(226, 116, 152);
|
||||||
|
configurationButton[0]->setButtonShape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
|
||||||
|
configurationButton[1] = std::make_unique<Button>(550, 465, 80, 20, "一键置1",
|
||||||
|
blackColor, RGB(171, 196, 220));
|
||||||
|
configurationButton[1]->textStyle.color = RGB(226, 116, 152);
|
||||||
|
configurationButton[1]->setButtonShape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
configurationButton[0]->setOnClickListener(
|
||||||
|
[&]() {
|
||||||
|
for (auto& s : selectionAreaButton_ptr)
|
||||||
|
if (s->isClicked()) s->setButtonClick(false);
|
||||||
|
|
||||||
|
// 刷新显示:prevThis 用当前 This 文本
|
||||||
|
const std::string prevThis = This->getText();
|
||||||
|
auto cur = snapshotBits();
|
||||||
|
{
|
||||||
|
char hexbuf[16];
|
||||||
|
uint32_t u = 0; for (int b = 0; b < 32; ++b) if (cur[b]) u |= (1u << b);
|
||||||
|
int32_t s = static_cast<int32_t>(u);
|
||||||
|
std::snprintf(hexbuf, sizeof(hexbuf), "%08X", u);
|
||||||
|
hex->setText(hexbuf);
|
||||||
|
dec->setText(gSigned ? std::to_string(s) : std::to_string(u));
|
||||||
|
Last->setText(prevThis);
|
||||||
|
This->setText(binaryGroupedFromBits(cur));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
configurationButton[1]->setOnClickListener(
|
||||||
|
[&]() {
|
||||||
|
for (auto& s : selectionAreaButton_ptr)
|
||||||
|
if (!s->isClicked()) s->setButtonClick(true);
|
||||||
|
|
||||||
|
const std::string prevThis = This->getText();
|
||||||
|
auto cur = snapshotBits();
|
||||||
|
char hexbuf[16];
|
||||||
|
uint32_t u = 0; for (int b = 0; b < 32; ++b) if (cur[b]) u |= (1u << b);
|
||||||
|
int32_t s = static_cast<int32_t>(u);
|
||||||
|
std::snprintf(hexbuf, sizeof(hexbuf), "%08X", u);
|
||||||
|
hex->setText(hexbuf);
|
||||||
|
dec->setText(gSigned ? std::to_string(s) : std::to_string(u));
|
||||||
|
Last->setText(prevThis);
|
||||||
|
This->setText(binaryGroupedFromBits(cur));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
auto signedToggle = std::make_unique<Button>(
|
||||||
|
350, 465, 80, 20, "无符号",
|
||||||
|
blackColor, RGB(171, 196, 220), StellarX::ButtonMode::TOGGLE);
|
||||||
|
signedToggle->textStyle.color = RGB(226, 116, 152);
|
||||||
|
signedToggle->setButtonShape(StellarX::ControlShape::B_RECTANGLE);
|
||||||
|
auto* signedTogglePtr = signedToggle.get();
|
||||||
|
|
||||||
|
signedTogglePtr->setOnToggleOnListener([&]() {
|
||||||
|
gSigned = true;
|
||||||
|
signedTogglePtr->setButtonText("有符号");
|
||||||
|
|
||||||
|
// 立即刷新十进制显示:用当前位图算出新值,仅改 dec
|
||||||
|
auto cur = snapshotBits();
|
||||||
|
const uint32_t u = [&] { uint32_t v = 0; for (int b = 0; b < 32; ++b) if (cur[b]) v |= (1u << b); return v; }();
|
||||||
|
const int32_t s = static_cast<int32_t>(u);
|
||||||
|
dec->setText(std::to_string(s));
|
||||||
|
});
|
||||||
|
signedTogglePtr->setOnToggleOffListener([&]() {
|
||||||
|
gSigned = false;
|
||||||
|
signedTogglePtr->setButtonText("无符号");
|
||||||
|
|
||||||
|
auto cur = snapshotBits();
|
||||||
|
const uint32_t u = [&] { uint32_t v = 0; for (int b = 0; b < 32; ++b) if (cur[b]) v |= (1u << b); return v; }();
|
||||||
|
dec->setText(std::to_string(u));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
configuration->addControl(std::move(configurationButton[0]));
|
||||||
|
configuration->addControl(std::move(configurationButton[1]));
|
||||||
|
configuration->addControl(std::move(signedToggle));
|
||||||
|
configuration->addControl(std::move(configurationLabel));
|
||||||
|
|
||||||
|
|
||||||
|
mainWindow.addControl(std::move(selectionArea));
|
||||||
|
mainWindow.addControl(std::move(function));
|
||||||
|
mainWindow.addControl(std::move(NumericalDisplayArea));
|
||||||
|
mainWindow.addControl(std::move(BinaryDisplayArea));
|
||||||
|
mainWindow.addControl(std::move(configuration));
|
||||||
|
|
||||||
|
mainWindow.draw();
|
||||||
|
return mainWindow.runEventLoop();
|
||||||
|
}
|
||||||
@@ -146,6 +146,7 @@ void TextBox::setText(std::string text)
|
|||||||
text = text.substr(0, maxCharLen);
|
text = text.substr(0, maxCharLen);
|
||||||
this->text = text;
|
this->text = text;
|
||||||
this->dirty = true;
|
this->dirty = true;
|
||||||
|
draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TextBox::getText() const
|
std::string TextBox::getText() const
|
||||||
|
|||||||
Reference in New Issue
Block a user