дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-08 19:02:17 +02:00
246 рядки
6.3 KiB
Rust
246 рядки
6.3 KiB
Rust
//! Views and custom editors (`[[contributes.views]]`,
|
|
//! `[[contributes.customEditors]]`): implement [`Views`] and register with
|
|
//! `register_plugin!(MyPlugin, views)`.
|
|
//!
|
|
//! A view is data — a toolbar, a body (tree, list, form, table, message or
|
|
//! sandboxed HTML) and a status line. The IDE renders it and calls
|
|
//! [`Views::handle`] with what the user did; call [`crate::host::refresh_view`]
|
|
//! when the content changes. For a custom editor, `ctx.editor()` is its
|
|
//! document: read it with `document()` and change it with `apply_edits`, so
|
|
//! the text editor of the same file follows and undo is shared.
|
|
|
|
use crate::{Error, Invocation};
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Button {
|
|
pub id: String,
|
|
pub label: String,
|
|
/// An IDE icon (`refresh`, `add`, `remove`, `run`, `stop`, `settings`…).
|
|
pub icon: Option<String>,
|
|
pub enabled: bool,
|
|
}
|
|
|
|
impl Button {
|
|
pub fn new(id: &str, label: &str) -> Self {
|
|
Self { id: id.into(), label: label.into(), icon: None, enabled: true }
|
|
}
|
|
|
|
pub fn icon(mut self, icon: &str) -> Self {
|
|
self.icon = Some(icon.into());
|
|
self
|
|
}
|
|
|
|
pub fn enabled(mut self, enabled: bool) -> Self {
|
|
self.enabled = enabled;
|
|
self
|
|
}
|
|
}
|
|
|
|
/// A tree node; `parent` is the key of an item listed before it.
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct TreeItem {
|
|
pub key: String,
|
|
pub parent: Option<String>,
|
|
pub label: String,
|
|
pub icon: Option<String>,
|
|
pub detail: Option<String>,
|
|
/// Shows an expander before the children are known ([`ViewEvent::Expand`]).
|
|
pub expandable: bool,
|
|
pub expanded: bool,
|
|
}
|
|
|
|
impl TreeItem {
|
|
pub fn new(key: &str, label: &str) -> Self {
|
|
Self {
|
|
key: key.into(),
|
|
parent: None,
|
|
label: label.into(),
|
|
icon: None,
|
|
detail: None,
|
|
expandable: false,
|
|
expanded: false,
|
|
}
|
|
}
|
|
|
|
pub fn parent(mut self, parent: &str) -> Self {
|
|
self.parent = Some(parent.into());
|
|
self
|
|
}
|
|
|
|
pub fn icon(mut self, icon: &str) -> Self {
|
|
self.icon = Some(icon.into());
|
|
self
|
|
}
|
|
|
|
pub fn detail(mut self, detail: &str) -> Self {
|
|
self.detail = Some(detail.into());
|
|
self
|
|
}
|
|
|
|
/// Has (or may have) children; `expanded` shows them.
|
|
pub fn expandable(mut self, expanded: bool) -> Self {
|
|
self.expandable = true;
|
|
self.expanded = expanded;
|
|
self
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct ListItem {
|
|
pub key: String,
|
|
pub label: String,
|
|
pub icon: Option<String>,
|
|
pub detail: Option<String>,
|
|
}
|
|
|
|
impl ListItem {
|
|
pub fn new(key: &str, label: &str) -> Self {
|
|
Self { key: key.into(), label: label.into(), icon: None, detail: None }
|
|
}
|
|
|
|
pub fn icon(mut self, icon: &str) -> Self {
|
|
self.icon = Some(icon.into());
|
|
self
|
|
}
|
|
|
|
pub fn detail(mut self, detail: &str) -> Self {
|
|
self.detail = Some(detail.into());
|
|
self
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
#[non_exhaustive]
|
|
pub enum FieldValue {
|
|
Text(String),
|
|
Multiline(String),
|
|
Checkbox(bool),
|
|
/// Options and the chosen one.
|
|
Choice(Vec<String>, String),
|
|
/// A field type of a newer plugin API: its kind and JSON data (IDEs that
|
|
/// don't know it leave the field out).
|
|
Other {
|
|
kind: String,
|
|
data: String,
|
|
},
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Field {
|
|
pub key: String,
|
|
pub label: String,
|
|
pub value: FieldValue,
|
|
}
|
|
|
|
impl Field {
|
|
pub fn new(key: &str, label: &str, value: FieldValue) -> Self {
|
|
Self { key: key.into(), label: label.into(), value }
|
|
}
|
|
}
|
|
|
|
/// Rows `first_row..first_row + rows.len()` of `total_rows`.
|
|
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
|
pub struct Table {
|
|
pub columns: Vec<String>,
|
|
pub total_rows: u32,
|
|
pub first_row: u32,
|
|
pub rows: Vec<Vec<String>>,
|
|
pub editable: bool,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
#[non_exhaustive]
|
|
pub enum Body {
|
|
Message(String),
|
|
Tree(Vec<TreeItem>),
|
|
List(Vec<ListItem>),
|
|
Form(Vec<Field>),
|
|
Table(Table),
|
|
/// Shown in a sandboxed frame; its script talks to the plugin with
|
|
/// `openidea.postMessage(text)` and `openidea.onMessage(fn)`.
|
|
Html(String),
|
|
/// A body of a newer plugin API: its kind and JSON data (IDEs that don't
|
|
/// know it say they need updating).
|
|
Other {
|
|
kind: String,
|
|
data: String,
|
|
},
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct View {
|
|
pub toolbar: Vec<Button>,
|
|
pub body: Body,
|
|
pub status: Option<String>,
|
|
}
|
|
|
|
impl View {
|
|
pub fn new(body: Body) -> Self {
|
|
Self { toolbar: Vec::new(), body, status: None }
|
|
}
|
|
|
|
pub fn message(text: &str) -> Self {
|
|
Self::new(Body::Message(text.into()))
|
|
}
|
|
|
|
pub fn button(mut self, b: Button) -> Self {
|
|
self.toolbar.push(b);
|
|
self
|
|
}
|
|
|
|
pub fn status(mut self, status: &str) -> Self {
|
|
self.status = Some(status.into());
|
|
self
|
|
}
|
|
}
|
|
|
|
/// The table rows the IDE shows (ask for no more than these).
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
pub struct Viewport {
|
|
pub first_row: u32,
|
|
pub rows: u32,
|
|
}
|
|
|
|
impl Viewport {
|
|
/// `first_row..end` clamped to `total`.
|
|
pub fn range(viewport: Option<Viewport>, total: u32, default_rows: u32) -> std::ops::Range<u32> {
|
|
let v = viewport.unwrap_or(Viewport { first_row: 0, rows: default_rows });
|
|
let start = v.first_row.min(total);
|
|
start..start.saturating_add(v.rows).min(total)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
#[non_exhaustive]
|
|
pub enum ViewEvent {
|
|
Button(String),
|
|
Activate(String),
|
|
Select(String),
|
|
Expand(String),
|
|
Collapse(String),
|
|
/// A form field: key and new value (`true`/`false` for checkboxes).
|
|
Field(String, String),
|
|
Cell {
|
|
row: u32,
|
|
column: u32,
|
|
value: String,
|
|
},
|
|
InsertRow(u32),
|
|
DeleteRows(Vec<u32>),
|
|
Message(String),
|
|
/// An event this SDK doesn't know: its kind and JSON data.
|
|
Other {
|
|
kind: String,
|
|
data: String,
|
|
},
|
|
}
|
|
|
|
/// Content of the plugin's declared views and custom editors.
|
|
pub trait Views {
|
|
fn render(&mut self, view: &str, viewport: Option<Viewport>, ctx: &Invocation) -> Result<View, Error>;
|
|
|
|
fn handle(&mut self, _view: &str, _event: ViewEvent, _ctx: &Invocation) -> Result<(), Error> {
|
|
Ok(())
|
|
}
|
|
}
|