Skip to main content

turbo_vision/
lib.rs

1// (C) 2025 - Enzo Lombardi
2
3//! Turbo Vision - A modern Text User Interface (TUI) framework for Rust.
4//!
5//! Turbo Vision is a Rust port of the classic Borland Turbo Vision framework,
6//! providing a powerful and flexible system for building terminal-based
7//! applications with a rich set of widgets and an event-driven architecture.
8//!
9//! # Features
10//!
11//! - **Event-driven architecture** - Handle keyboard, mouse, and custom events
12//! - **Flexible view hierarchy** - Compose UIs from reusable widget components
13//! - **Built-in widgets** - Windows, dialogs, buttons, input fields, lists, menus
14//! - **Syntax highlighting** - Extensible syntax highlighting system for editors
15//! - **Command system** - Global command routing and enable/disable states
16//! - **Clipboard support** - Copy/paste operations
17//! - **History management** - Input history for text fields
18//! - **Double-buffered rendering** - Flicker-free terminal updates
19//! - **Mouse support** - Full mouse capture and tracking
20//! - **Borland TV compatibility** - Familiar API for Turbo Vision users
21//!
22//! # Quick Start
23//!
24//! ```rust,no_run
25//! use turbo_vision::prelude::*;
26//!
27//! fn main() -> turbo_vision::core::error::Result<()> {
28//!     // Create application with terminal
29//!     let mut app = Application::new()?;
30//!
31//!     // Create a simple window
32//!     let mut window = turbo_vision::views::window::Window::new(
33//!         Rect::new(10, 5, 50, 15),
34//!         "My First Window"
35//!     );
36//!
37//!     // Add a button
38//!     let button = turbo_vision::views::button::Button::new(
39//!         Rect::new(15, 5, 25, 7),
40//!         "Click Me",
41//!         turbo_vision::core::command::CM_OK,
42//!         false
43//!     );
44//!     window.add(Box::new(button));
45//!
46//!     // Add window to desktop
47//!     app.desktop.add(Box::new(window));
48//!
49//!     // Run event loop
50//!     app.running = true;
51//!     while app.running {
52//!         app.desktop.draw(&mut app.terminal);
53//!         app.terminal.flush()?;
54//!
55//!         if let Ok(Some(mut event)) = app.terminal.poll_event(
56//!             std::time::Duration::from_millis(50)
57//!         ) {
58//!             app.desktop.handle_event(&mut event);
59//!
60//!             if event.what == EventType::Command {
61//!                 match event.command {
62//!                     CM_QUIT => app.running = false,
63//!                     CM_OK => {
64//!                         // Handle button click
65//!                         app.running = false;
66//!                     }
67//!                     _ => {}
68//!                 }
69//!             }
70//!         }
71//!     }
72//!
73//!     app.terminal.shutdown()?;
74//!     Ok(())
75//! }
76//! ```
77//!
78//! # Architecture
79//!
80//! The framework is organized into several key modules:
81//!
82//! ## Core Modules
83//!
84//! - **[`core`]** - Fundamental types and utilities
85//!   - [`geometry`](core::geometry) - Point, Rect for positioning
86//!   - [`event`](core::event) - Event handling and keyboard/mouse input
87//!   - [`command`](core::command) - Command IDs and routing
88//!   - [`error`](core::error) - Error types and Result alias
89//!   - [`palette`](core::palette) - Color management
90//!
91//! - **[`views`]** - Built-in widgets and view components
92//!   - [`View`](views::View) - Base trait for all UI components
93//!   - [`Window`](views::window::Window), [`Dialog`](views::dialog::Dialog) - Containers
94//!   - [`Button`](views::button::Button), [`InputLine`](views::input_line::InputLine) - Controls
95//!   - [`Editor`](views::editor::Editor) - Multi-line text editor
96//!   - [`MenuBar`](views::menu_bar::MenuBar), [`StatusLine`](views::status_line::StatusLine) - Navigation
97//!
98//! - **[`app`]** - Application infrastructure
99//!   - [`Application`](app::Application) - Main application coordinator
100//!
101//! - **[`terminal`]** - Terminal abstraction layer
102//!   - [`Terminal`](terminal::Terminal) - Crossterm-based rendering backend
103//!
104//! ## Application Structure
105//!
106//! ```text
107//! Application
108//! ├── Terminal (crossterm backend)
109//! ├── Desktop (window manager)
110//! │   ├── Background
111//! │   └── Windows/Dialogs
112//! │       └── Child widgets (buttons, inputs, etc.)
113//! ├── MenuBar (optional)
114//! └── StatusLine (optional)
115//! ```
116//!
117//! # Examples
118//!
119//! ## Creating a Dialog
120//!
121//! ```rust,no_run
122//! use turbo_vision::prelude::*;
123//! use turbo_vision::views::{dialog::Dialog, button::Button, static_text::StaticText};
124//!
125//! # fn create_dialog() -> Box<Dialog> {
126//! let dialog_bounds = Rect::new(20, 8, 60, 16);
127//! let mut dialog = Dialog::new_modal(dialog_bounds, "Confirmation");
128//!
129//! // Add message text
130//! let text = StaticText::new(
131//!     Rect::new(2, 2, 38, 3),
132//!     "Are you sure you want to continue?"
133//! );
134//! dialog.add(Box::new(text));
135//!
136//! // Add OK button
137//! let ok_button = Button::new(
138//!     Rect::new(10, 4, 18, 6),
139//!     "OK",
140//!     turbo_vision::core::command::CM_OK,
141//!     true  // default button
142//! );
143//! dialog.add(Box::new(ok_button));
144//!
145//! // Add Cancel button
146//! let cancel_button = Button::new(
147//!     Rect::new(22, 4, 32, 6),
148//!     "Cancel",
149//!     turbo_vision::core::command::CM_CANCEL,
150//!     false
151//! );
152//! dialog.add(Box::new(cancel_button));
153//!
154//! dialog
155//! # }
156//! ```
157//!
158//! ## Handling Events
159//!
160//! ```rust,no_run
161//! use turbo_vision::prelude::*;
162//! # use turbo_vision::app::Application;
163//! # use turbo_vision::core::error::Result;
164//! # fn example(mut app: Application) -> Result<()> {
165//!
166//! app.running = true;
167//! while app.running {
168//!     // Draw UI
169//!     app.desktop.draw(&mut app.terminal);
170//!     app.terminal.flush()?;
171//!
172//!     // Poll for events
173//!     if let Ok(Some(mut event)) = app.terminal.poll_event(
174//!         std::time::Duration::from_millis(50)
175//!     ) {
176//!         // Let desktop handle event
177//!         app.desktop.handle_event(&mut event);
178//!
179//!         // Check for commands
180//!         if event.what == EventType::Command {
181//!             match event.command {
182//!                 CM_QUIT => {
183//!                     app.running = false;
184//!                 }
185//!                 _ => {}
186//!             }
187//!         }
188//!     }
189//! }
190//! # Ok(())
191//! # }
192//! ```
193//!
194//! # Borland Turbo Vision Compatibility
195//!
196//! This implementation maintains conceptual compatibility with Borland Turbo Vision
197//! while modernizing the design for Rust's ownership model:
198//!
199//! - **TView** → [`View`](views::View) trait
200//! - **TWindow** → [`Window`](views::window::Window)
201//! - **TDialog** → [`Dialog`](views::dialog::Dialog)
202//! - **TButton** → [`Button`](views::button::Button)
203//! - **TInputLine** → [`InputLine`](views::input_line::InputLine)
204//! - **TProgram** → [`Application`](app::Application)
205//!
206//! Event handling uses Rust's ownership system instead of raw pointers, with
207//! events bubbling up through the call stack rather than using owner pointers.
208//!
209//! # See Also
210//!
211//! - [Examples](https://github.com/anthropics/turbo-vision/tree/main/examples) - Complete working examples
212//! - [Borland TV Documentation](https://github.com/magiblot/tvision) - Original reference
213
214// Core modules
215pub mod core;
216pub mod terminal;
217pub mod views;
218pub mod app;
219pub mod helpers;
220
221// SSH server support (only available with ssh feature)
222#[cfg(feature = "ssh")]
223pub mod ssh;
224
225// Test utilities (only available with test-util feature)
226#[cfg(feature = "test-util")]
227pub mod test_util;
228
229// Re-export commonly used types
230pub mod prelude {
231    pub use crate::core::geometry::{Point, Rect};
232    pub use crate::core::event::{Event, EventType, KeyCode};
233
234    // Explicit command re-exports (no glob imports)
235    pub use crate::core::command::{
236        CommandId,
237        // Basic dialog commands
238        CM_QUIT,
239        CM_CLOSE,
240        CM_OK,
241        CM_CANCEL,
242        CM_YES,
243        CM_NO,
244        CM_DEFAULT,
245        // Internal view system commands
246        CM_COMMAND_SET_CHANGED,
247        CM_RECEIVED_FOCUS,
248        CM_RELEASED_FOCUS,
249        CM_GRAB_DEFAULT,
250        CM_RELEASE_DEFAULT,
251        CM_FILE_FOCUSED,
252        CM_FILE_DOUBLE_CLICKED,
253        // Application commands
254        CM_ABOUT,
255        CM_BIRTHDATE,
256        CM_TEXT_VIEWER,
257        CM_CONTROLS_DEMO,
258        // File operations
259        CM_NEW,
260        CM_OPEN,
261        CM_SAVE,
262        CM_SAVE_AS,
263        CM_SAVE_ALL,
264        CM_CLOSE_FILE,
265        // Edit operations
266        CM_UNDO,
267        CM_REDO,
268        CM_CUT,
269        CM_COPY,
270        CM_PASTE,
271        CM_SELECT_ALL,
272        CM_FIND,
273        CM_REPLACE,
274        CM_SEARCH_AGAIN,
275        CM_FIND_IN_FILES,
276        CM_GOTO_LINE,
277        // View commands
278        CM_ZOOM_IN,
279        CM_ZOOM_OUT,
280        CM_TOGGLE_SIDEBAR,
281        CM_TOGGLE_STATUSBAR,
282        // Help commands
283        CM_HELP_INDEX,
284        CM_KEYBOARD_REF,
285        // Demo commands
286        CM_LISTBOX_DEMO,
287        CM_LISTBOX_SELECT,
288        CM_MEMO_DEMO,
289    };
290
291    pub use crate::views::View;
292    pub use crate::app::Application;
293}