mirror of
https://github.com/penpot/penpot.git
synced 2026-09-12 23:19:28 +00:00
🎉 Feat apply styles to selection
This commit is contained in:
parent
0f389fe3ad
commit
12382cfbb9
@ -788,14 +788,15 @@
|
|||||||
(when (features/active-feature? state "render-wasm/v1")
|
(when (features/active-feature? state "render-wasm/v1")
|
||||||
(rx/concat
|
(rx/concat
|
||||||
;; Apply style to selected spans and sync content
|
;; Apply style to selected spans and sync content
|
||||||
(when (wasm.api/text-editor-is-active?)
|
(let [has-selection? (wasm.api/text-editor-has-selection?)]
|
||||||
(let [span-attrs (select-keys attrs txt/text-node-attrs)]
|
(when has-selection?
|
||||||
(when (not (empty? span-attrs))
|
(let [span-attrs (select-keys attrs txt/text-node-attrs)]
|
||||||
(let [result (wasm.api/apply-style-to-selection span-attrs)]
|
(when (not (empty? span-attrs))
|
||||||
(when result
|
(let [result (wasm.api/apply-style-to-selection span-attrs)]
|
||||||
(rx/of (v2-update-text-shape-content
|
(when result
|
||||||
(:shape-id result) (:content result)
|
(rx/of (v2-update-text-shape-content
|
||||||
:update-name? true)))))))
|
(:shape-id result) (:content result)
|
||||||
|
:update-name? true))))))))
|
||||||
;; Resize (with delay for font-id changes)
|
;; Resize (with delay for font-id changes)
|
||||||
(cond->> (rx/of (dwwt/resize-wasm-text id))
|
(cond->> (rx/of (dwwt/resize-wasm-text id))
|
||||||
(contains? attrs :font-id)
|
(contains? attrs :font-id)
|
||||||
|
|||||||
@ -120,7 +120,7 @@
|
|||||||
on-copy
|
on-copy
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [^js event]
|
(fn [^js event]
|
||||||
(when (text-editor/text-editor-is-active?)
|
(when (text-editor/text-editor-has-focus?)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(when (text-editor/text-editor-get-selection)
|
(when (text-editor/text-editor-get-selection)
|
||||||
(let [text (text-editor/text-editor-export-selection)]
|
(let [text (text-editor/text-editor-export-selection)]
|
||||||
@ -129,7 +129,7 @@
|
|||||||
on-cut
|
on-cut
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [^js event]
|
(fn [^js event]
|
||||||
(when (text-editor/text-editor-is-active?)
|
(when (text-editor/text-editor-has-focus?)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(when (text-editor/text-editor-get-selection)
|
(when (text-editor/text-editor-get-selection)
|
||||||
(let [text (text-editor/text-editor-export-selection)]
|
(let [text (text-editor/text-editor-export-selection)]
|
||||||
@ -144,7 +144,7 @@
|
|||||||
on-key-down
|
on-key-down
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [^js event]
|
(fn [^js event]
|
||||||
(when (and (text-editor/text-editor-is-active?)
|
(when (and (text-editor/text-editor-has-focus?)
|
||||||
(not @composing?))
|
(not @composing?))
|
||||||
(let [key (.-key event)
|
(let [key (.-key event)
|
||||||
ctrl? (or (.-ctrlKey event) (.-metaKey event))
|
ctrl? (or (.-ctrlKey event) (.-metaKey event))
|
||||||
@ -283,13 +283,13 @@
|
|||||||
on-focus
|
on-focus
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [^js _event]
|
(fn [^js _event]
|
||||||
(wasm.api/text-editor-start shape-id)))
|
(wasm.api/text-editor-focus shape-id)))
|
||||||
|
|
||||||
on-blur
|
on-blur
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [^js _event]
|
(fn [^js _event]
|
||||||
(sync-wasm-text-editor-content! {:finalize? true})
|
(sync-wasm-text-editor-content! {:finalize? true})
|
||||||
(wasm.api/text-editor-stop)))
|
(wasm.api/text-editor-blur)))
|
||||||
|
|
||||||
style #js {:pointerEvents "all"
|
style #js {:pointerEvents "all"
|
||||||
"--editor-container-width" (dm/str width "px")
|
"--editor-container-width" (dm/str width "px")
|
||||||
@ -312,11 +312,15 @@
|
|||||||
(fn []
|
(fn []
|
||||||
(let [timeout-id (atom nil)
|
(let [timeout-id (atom nil)
|
||||||
schedule-blink (fn schedule-blink []
|
schedule-blink (fn schedule-blink []
|
||||||
(when (text-editor/text-editor-is-active?)
|
(when (text-editor/text-editor-has-focus?)
|
||||||
(wasm.api/request-render "cursor-blink"))
|
(wasm.api/request-render "cursor-blink"))
|
||||||
(reset! timeout-id (js/setTimeout schedule-blink caret-blink-interval-ms)))]
|
(reset! timeout-id (js/setTimeout schedule-blink caret-blink-interval-ms)))]
|
||||||
(schedule-blink)
|
(schedule-blink)
|
||||||
(fn []
|
(fn []
|
||||||
|
;; ESTO ES JUSTO LO QUE NO QUIERO, NO QUIERO QUE SE HAGA
|
||||||
|
;; DISPOSE CUANDO SE DESMONTA EL COMPONENTE.
|
||||||
|
#_(when (text-editor/text-editor-dispose)
|
||||||
|
(wasm.api/request-render "text-editor-dispose"))
|
||||||
(when @timeout-id
|
(when @timeout-id
|
||||||
(js/clearTimeout @timeout-id))))))
|
(js/clearTimeout @timeout-id))))))
|
||||||
|
|
||||||
|
|||||||
@ -292,7 +292,7 @@
|
|||||||
(when left-click?
|
(when left-click?
|
||||||
(st/emit! (mse/->MouseEvent :up ctrl? shift? alt? meta?))
|
(st/emit! (mse/->MouseEvent :up ctrl? shift? alt? meta?))
|
||||||
|
|
||||||
(when (wasm.api/text-editor-is-active?)
|
(when (wasm.api/text-editor-has-focus?)
|
||||||
(wasm.api/text-editor-pointer-up (.-x off-pt) (.-y off-pt))))
|
(wasm.api/text-editor-pointer-up (.-x off-pt) (.-y off-pt))))
|
||||||
|
|
||||||
(when middle-click?
|
(when middle-click?
|
||||||
|
|||||||
@ -92,14 +92,15 @@
|
|||||||
(def clear-canvas-pixels webgl/clear-canvas-pixels)
|
(def clear-canvas-pixels webgl/clear-canvas-pixels)
|
||||||
|
|
||||||
;; Re-export public text editor functions
|
;; Re-export public text editor functions
|
||||||
(def text-editor-start text-editor/text-editor-start)
|
(def text-editor-focus text-editor/text-editor-focus)
|
||||||
(def text-editor-stop text-editor/text-editor-stop)
|
(def text-editor-blur text-editor/text-editor-blur)
|
||||||
(def text-editor-set-cursor-from-offset text-editor/text-editor-set-cursor-from-offset)
|
(def text-editor-set-cursor-from-offset text-editor/text-editor-set-cursor-from-offset)
|
||||||
(def text-editor-set-cursor-from-point text-editor/text-editor-set-cursor-from-point)
|
(def text-editor-set-cursor-from-point text-editor/text-editor-set-cursor-from-point)
|
||||||
(def text-editor-pointer-down text-editor/text-editor-pointer-down)
|
(def text-editor-pointer-down text-editor/text-editor-pointer-down)
|
||||||
(def text-editor-pointer-move text-editor/text-editor-pointer-move)
|
(def text-editor-pointer-move text-editor/text-editor-pointer-move)
|
||||||
(def text-editor-pointer-up text-editor/text-editor-pointer-up)
|
(def text-editor-pointer-up text-editor/text-editor-pointer-up)
|
||||||
(def text-editor-is-active? text-editor/text-editor-is-active?)
|
(def text-editor-has-focus? text-editor/text-editor-has-focus?)
|
||||||
|
(def text-editor-has-selection? text-editor/text-editor-has-selection?)
|
||||||
(def text-editor-select-all text-editor/text-editor-select-all)
|
(def text-editor-select-all text-editor/text-editor-select-all)
|
||||||
(def text-editor-select-word-boundary text-editor/text-editor-select-word-boundary)
|
(def text-editor-select-word-boundary text-editor/text-editor-select-word-boundary)
|
||||||
(def text-editor-sync-content text-editor/text-editor-sync-content)
|
(def text-editor-sync-content text-editor/text-editor-sync-content)
|
||||||
@ -136,6 +137,13 @@
|
|||||||
:fill "none"}
|
:fill "none"}
|
||||||
[:& shape-wrapper {:shape shape}]]))
|
[:& shape-wrapper {:shape shape}]]))
|
||||||
|
|
||||||
|
(defn is-text-editor-wasm-enabled
|
||||||
|
[state]
|
||||||
|
(let [runtime-features (get state :features-runtime)
|
||||||
|
enabled-features (get state :features)]
|
||||||
|
(or (contains? runtime-features "text-editor-wasm/v1")
|
||||||
|
(contains? enabled-features "text-editor-wasm/v1"))))
|
||||||
|
|
||||||
(defn get-static-markup
|
(defn get-static-markup
|
||||||
[shape]
|
[shape]
|
||||||
(->
|
(->
|
||||||
@ -155,17 +163,17 @@
|
|||||||
;; Update text editor blink (so cursor toggles) using the same timestamp
|
;; Update text editor blink (so cursor toggles) using the same timestamp
|
||||||
(try
|
(try
|
||||||
(when wasm/context-initialized?
|
(when wasm/context-initialized?
|
||||||
(text-editor/text-editor-update-blink timestamp)
|
|
||||||
;; Render text editor overlay on top of main canvas (only if feature enabled)
|
;; Render text editor overlay on top of main canvas (only if feature enabled)
|
||||||
;; Determine if text-editor-wasm feature is active without requiring
|
;; Determine if text-editor-wasm feature is active without requiring
|
||||||
;; app.main.features to avoid circular dependency: check runtime and
|
;; app.main.features to avoid circular dependency: check runtime and
|
||||||
;; persisted feature sets in the store state.
|
;; persisted feature sets in the store state.
|
||||||
(when (text-editor-wasm?)
|
(when (is-text-editor-wasm-enabled @st/state)
|
||||||
(text-editor/text-editor-render-overlay))
|
(text-editor/text-editor-update-blink timestamp)
|
||||||
;; Poll for editor events; if any event occurs, trigger a re-render
|
(text-editor/text-editor-render-overlay)
|
||||||
(let [ev (text-editor/text-editor-poll-event)]
|
;; Poll for editor events; if any event occurs, trigger a re-render
|
||||||
(when (and ev (not= ev 0))
|
(let [ev (text-editor/text-editor-poll-event)]
|
||||||
(request-render "text-editor-event"))))
|
(when (and ev (not= ev 0))
|
||||||
|
(request-render "text-editor-event")))))
|
||||||
(catch :default e
|
(catch :default e
|
||||||
(js/console.error "text-editor overlay/update failed:" e)))
|
(js/console.error "text-editor overlay/update failed:" e)))
|
||||||
|
|
||||||
|
|||||||
@ -12,16 +12,16 @@
|
|||||||
[app.render-wasm.mem :as mem]
|
[app.render-wasm.mem :as mem]
|
||||||
[app.render-wasm.wasm :as wasm]))
|
[app.render-wasm.wasm :as wasm]))
|
||||||
|
|
||||||
(defn text-editor-start
|
(defn text-editor-focus
|
||||||
[id]
|
[id]
|
||||||
(when wasm/context-initialized?
|
(when wasm/context-initialized?
|
||||||
(let [buffer (uuid/get-u32 id)]
|
(let [buffer (uuid/get-u32 id)]
|
||||||
(when-not (h/call wasm/internal-module "_text_editor_start"
|
(when-not (h/call wasm/internal-module "_text_editor_focus"
|
||||||
(aget buffer 0)
|
(aget buffer 0)
|
||||||
(aget buffer 1)
|
(aget buffer 1)
|
||||||
(aget buffer 2)
|
(aget buffer 2)
|
||||||
(aget buffer 3))
|
(aget buffer 3))
|
||||||
(throw (js/Error. "TextEditor initialization failed"))))))
|
(throw (js/Error. "TextEditor focus failed"))))))
|
||||||
|
|
||||||
(defn text-editor-set-cursor-from-offset
|
(defn text-editor-set-cursor-from-offset
|
||||||
"Sets caret position from shape relative coordinates"
|
"Sets caret position from shape relative coordinates"
|
||||||
@ -142,19 +142,29 @@
|
|||||||
(when wasm/context-initialized?
|
(when wasm/context-initialized?
|
||||||
(h/call wasm/internal-module "_text_editor_select_word_boundary" x y)))
|
(h/call wasm/internal-module "_text_editor_select_word_boundary" x y)))
|
||||||
|
|
||||||
(defn text-editor-stop
|
(defn text-editor-blur
|
||||||
[]
|
[]
|
||||||
(when wasm/context-initialized?
|
(when wasm/context-initialized?
|
||||||
(when-not (h/call wasm/internal-module "_text_editor_stop")
|
(when-not (h/call wasm/internal-module "_text_editor_blur")
|
||||||
(throw (js/Error. "TextEditor finalization failed")))))
|
(throw (js/Error. "TextEditor blur failed")))))
|
||||||
|
|
||||||
(defn text-editor-is-active?
|
(defn text-editor-dispose
|
||||||
|
[]
|
||||||
|
(when wasm/context-initialized?
|
||||||
|
(h/call wasm/internal-module "_text_editor_dispose")))
|
||||||
|
|
||||||
|
(defn text-editor-has-focus?
|
||||||
([id]
|
([id]
|
||||||
(when wasm/context-initialized?
|
(when wasm/context-initialized?
|
||||||
(not (zero? (h/call wasm/internal-module "_text_editor_is_active_with_id" id)))))
|
(not (zero? (h/call wasm/internal-module "_text_editor_has_focus_with_id" id)))))
|
||||||
([]
|
([]
|
||||||
(when wasm/context-initialized?
|
(when wasm/context-initialized?
|
||||||
(not (zero? (h/call wasm/internal-module "_text_editor_is_active"))))))
|
(not (zero? (h/call wasm/internal-module "_text_editor_has_focus"))))))
|
||||||
|
|
||||||
|
(defn text-editor-has-selection?
|
||||||
|
([]
|
||||||
|
(when wasm/context-initialized?
|
||||||
|
(not (zero? (h/call wasm/internal-module "_text_editor_has_selection"))))))
|
||||||
|
|
||||||
(defn text-editor-export-content
|
(defn text-editor-export-content
|
||||||
[]
|
[]
|
||||||
@ -198,18 +208,20 @@
|
|||||||
(defn text-editor-get-selection
|
(defn text-editor-get-selection
|
||||||
[]
|
[]
|
||||||
(when wasm/context-initialized?
|
(when wasm/context-initialized?
|
||||||
(let [byte-offset (mem/alloc 16)
|
(let [byte-offset (mem/alloc 16)
|
||||||
u32-offset (mem/->offset-32 byte-offset)
|
u32-offset (mem/->offset-32 byte-offset)
|
||||||
heap (mem/get-heap-u32)
|
heap (mem/get-heap-u32)
|
||||||
active? (h/call wasm/internal-module "_text_editor_get_selection" byte-offset)]
|
has-selection? (h/call wasm/internal-module "_text_editor_get_selection" byte-offset)]
|
||||||
(try
|
(if has-selection?
|
||||||
(when (= active? 1)
|
(let [result {:anchor-para (aget heap u32-offset)
|
||||||
{:anchor-para (aget heap u32-offset)
|
:anchor-offset (aget heap (+ u32-offset 1))
|
||||||
:anchor-offset (aget heap (+ u32-offset 1))
|
:focus-para (aget heap (+ u32-offset 2))
|
||||||
:focus-para (aget heap (+ u32-offset 2))
|
:focus-offset (aget heap (+ u32-offset 3))}]
|
||||||
:focus-offset (aget heap (+ u32-offset 3))})
|
(mem/free)
|
||||||
(finally
|
result)
|
||||||
(mem/free))))))
|
(do
|
||||||
|
(mem/free)
|
||||||
|
nil)))))
|
||||||
|
|
||||||
;; This is used as a intermediate cache between Clojure global state and WASM state.
|
;; This is used as a intermediate cache between Clojure global state and WASM state.
|
||||||
(def ^:private shape-text-contents (atom {}))
|
(def ^:private shape-text-contents (atom {}))
|
||||||
@ -260,7 +272,7 @@
|
|||||||
shape-id and the fully merged content map ready for
|
shape-id and the fully merged content map ready for
|
||||||
v2-update-text-shape-content."
|
v2-update-text-shape-content."
|
||||||
[]
|
[]
|
||||||
(when (and wasm/context-initialized? (text-editor-is-active?))
|
(when (and wasm/context-initialized? (text-editor-has-focus?))
|
||||||
(let [shape-id (text-editor-get-active-shape-id)
|
(let [shape-id (text-editor-get-active-shape-id)
|
||||||
new-texts (text-editor-export-content)]
|
new-texts (text-editor-export-content)]
|
||||||
(when (and shape-id new-texts)
|
(when (and shape-id new-texts)
|
||||||
@ -332,7 +344,7 @@
|
|||||||
|
|
||||||
(defn apply-style-to-selection
|
(defn apply-style-to-selection
|
||||||
[attrs use-shape-fn set-shape-text-content-fn]
|
[attrs use-shape-fn set-shape-text-content-fn]
|
||||||
(when (and wasm/context-initialized? (text-editor-is-active?))
|
(when wasm/context-initialized?
|
||||||
(let [shape-id (text-editor-get-active-shape-id)
|
(let [shape-id (text-editor-get-active-shape-id)
|
||||||
sel (text-editor-get-selection)]
|
sel (text-editor-get-selection)]
|
||||||
(when (and shape-id sel)
|
(when (and shape-id sel)
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use skia_safe::textlayout::{RectHeightStyle, RectWidthStyle};
|
|||||||
use skia_safe::{BlendMode, Canvas, Paint, Rect};
|
use skia_safe::{BlendMode, Canvas, Paint, Rect};
|
||||||
|
|
||||||
pub fn render_overlay(canvas: &Canvas, editor_state: &TextEditorState, shape: &Shape) {
|
pub fn render_overlay(canvas: &Canvas, editor_state: &TextEditorState, shape: &Shape) {
|
||||||
if !editor_state.is_active {
|
if !editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -165,7 +165,7 @@ pub struct TextEditorState {
|
|||||||
pub theme: TextEditorTheme,
|
pub theme: TextEditorTheme,
|
||||||
pub selection: TextSelection,
|
pub selection: TextSelection,
|
||||||
pub composition: TextComposition,
|
pub composition: TextComposition,
|
||||||
pub is_active: bool,
|
pub has_focus: bool,
|
||||||
// This property indicates that we've started
|
// This property indicates that we've started
|
||||||
// selecting something with the pointer.
|
// selecting something with the pointer.
|
||||||
pub is_pointer_selection_active: bool,
|
pub is_pointer_selection_active: bool,
|
||||||
@ -185,7 +185,7 @@ impl TextEditorState {
|
|||||||
},
|
},
|
||||||
selection: TextSelection::new(),
|
selection: TextSelection::new(),
|
||||||
composition: TextComposition::new(),
|
composition: TextComposition::new(),
|
||||||
is_active: false,
|
has_focus: false,
|
||||||
is_pointer_selection_active: false,
|
is_pointer_selection_active: false,
|
||||||
active_shape_id: None,
|
active_shape_id: None,
|
||||||
cursor_visible: true,
|
cursor_visible: true,
|
||||||
@ -194,8 +194,8 @@ impl TextEditorState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&mut self, shape_id: Uuid) {
|
pub fn focus(&mut self, shape_id: Uuid) {
|
||||||
self.is_active = true;
|
self.has_focus = true;
|
||||||
self.active_shape_id = Some(shape_id);
|
self.active_shape_id = Some(shape_id);
|
||||||
self.cursor_visible = true;
|
self.cursor_visible = true;
|
||||||
self.last_blink_time = 0.0;
|
self.last_blink_time = 0.0;
|
||||||
@ -204,8 +204,18 @@ impl TextEditorState {
|
|||||||
self.pending_events.clear();
|
self.pending_events.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop(&mut self) {
|
pub fn blur(&mut self) {
|
||||||
self.is_active = false;
|
self.has_focus = false;
|
||||||
|
// self.active_shape_id = None;
|
||||||
|
self.cursor_visible = false;
|
||||||
|
self.last_blink_time = 0.0;
|
||||||
|
// self.selection.reset();
|
||||||
|
self.is_pointer_selection_active = false;
|
||||||
|
self.pending_events.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispose(&mut self) {
|
||||||
|
self.has_focus = false;
|
||||||
self.active_shape_id = None;
|
self.active_shape_id = None;
|
||||||
self.cursor_visible = false;
|
self.cursor_visible = false;
|
||||||
self.last_blink_time = 0.0;
|
self.last_blink_time = 0.0;
|
||||||
@ -344,7 +354,7 @@ impl TextEditorState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_blink(&mut self, timestamp_ms: f64) {
|
pub fn update_blink(&mut self, timestamp_ms: f64) {
|
||||||
if !self.is_active {
|
if !self.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ pub extern "C" fn text_editor_apply_theme(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_start(a: u32, b: u32, c: u32, d: u32) -> bool {
|
pub extern "C" fn text_editor_focus(a: u32, b: u32, c: u32, d: u32) -> bool {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
let shape_id = uuid_from_u32_quartet(a, b, c, d);
|
let shape_id = uuid_from_u32_quartet(a, b, c, d);
|
||||||
|
|
||||||
@ -56,35 +56,48 @@ pub extern "C" fn text_editor_start(a: u32, b: u32, c: u32, d: u32) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.text_editor_state.start(shape_id);
|
state.text_editor_state.focus(shape_id);
|
||||||
true
|
true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_stop() -> bool {
|
pub extern "C" fn text_editor_blur() -> bool {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
state.text_editor_state.stop();
|
state.text_editor_state.blur();
|
||||||
true
|
true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_is_active() -> bool {
|
pub extern "C" fn text_editor_dispose() -> bool {
|
||||||
with_state!(state, { state.text_editor_state.is_active })
|
with_state_mut!(state, {
|
||||||
|
state.text_editor_state.dispose();
|
||||||
|
true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_is_active_with_id(a: u32, b: u32, c: u32, d: u32) -> bool {
|
pub extern "C" fn text_editor_has_selection() -> bool {
|
||||||
|
with_state!(state, { state.text_editor_state.selection.is_selection() })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn text_editor_has_focus() -> bool {
|
||||||
|
with_state!(state, { state.text_editor_state.has_focus })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn text_editor_has_focus_with_id(a: u32, b: u32, c: u32, d: u32) -> bool {
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
let shape_id = uuid_from_u32_quartet(a, b, c, d);
|
let shape_id = uuid_from_u32_quartet(a, b, c, d);
|
||||||
let Some(active_shape_id) = state.text_editor_state.active_shape_id else {
|
let Some(active_shape_id) = state.text_editor_state.active_shape_id else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
state.text_editor_state.is_active && active_shape_id == shape_id
|
state.text_editor_state.has_focus && active_shape_id == shape_id
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +119,7 @@ pub extern "C" fn text_editor_get_active_shape_id(buffer_ptr: *mut u32) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_select_all() -> bool {
|
pub extern "C" fn text_editor_select_all() -> bool {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +141,7 @@ pub extern "C" fn text_editor_select_all() -> bool {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_select_word_boundary(x: f32, y: f32) {
|
pub extern "C" fn text_editor_select_word_boundary(x: f32, y: f32) {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +178,7 @@ pub extern "C" fn text_editor_poll_event() -> u8 {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_pointer_down(x: f32, y: f32) {
|
pub extern "C" fn text_editor_pointer_down(x: f32, y: f32) {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let Some(shape_id) = state.text_editor_state.active_shape_id else {
|
let Some(shape_id) = state.text_editor_state.active_shape_id else {
|
||||||
@ -188,7 +201,7 @@ pub extern "C" fn text_editor_pointer_down(x: f32, y: f32) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_pointer_move(x: f32, y: f32) {
|
pub extern "C" fn text_editor_pointer_move(x: f32, y: f32) {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let point = Point::new(x, y);
|
let point = Point::new(x, y);
|
||||||
@ -216,7 +229,7 @@ pub extern "C" fn text_editor_pointer_move(x: f32, y: f32) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_pointer_up(x: f32, y: f32) {
|
pub extern "C" fn text_editor_pointer_up(x: f32, y: f32) {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let point = Point::new(x, y);
|
let point = Point::new(x, y);
|
||||||
@ -244,7 +257,7 @@ pub extern "C" fn text_editor_pointer_up(x: f32, y: f32) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_set_cursor_from_offset(x: f32, y: f32) {
|
pub extern "C" fn text_editor_set_cursor_from_offset(x: f32, y: f32) {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +280,7 @@ pub extern "C" fn text_editor_set_cursor_from_offset(x: f32, y: f32) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_set_cursor_from_point(x: f32, y: f32) {
|
pub extern "C" fn text_editor_set_cursor_from_point(x: f32, y: f32) {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +448,7 @@ pub extern "C" fn text_editor_insert_text() -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +501,7 @@ pub extern "C" fn text_editor_insert_text() -> Result<()> {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_delete_backward(word_boundary: bool) {
|
pub extern "C" fn text_editor_delete_backward(word_boundary: bool) {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,7 +554,7 @@ pub extern "C" fn text_editor_delete_backward(word_boundary: bool) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_delete_forward(word_boundary: bool) {
|
pub extern "C" fn text_editor_delete_forward(word_boundary: bool) {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +607,7 @@ pub extern "C" fn text_editor_delete_forward(word_boundary: bool) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_insert_paragraph() {
|
pub extern "C" fn text_editor_insert_paragraph() {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,7 +665,7 @@ pub extern "C" fn text_editor_move_cursor(
|
|||||||
extend_selection: bool,
|
extend_selection: bool,
|
||||||
) {
|
) {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,7 +748,7 @@ pub extern "C" fn text_editor_move_cursor(
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_get_cursor_rect() -> *mut u8 {
|
pub extern "C" fn text_editor_get_cursor_rect() -> *mut u8 {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active || !state.text_editor_state.cursor_visible {
|
if !state.text_editor_state.has_focus || !state.text_editor_state.cursor_visible {
|
||||||
return std::ptr::null_mut();
|
return std::ptr::null_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,7 +782,7 @@ pub extern "C" fn text_editor_get_cursor_rect() -> *mut u8 {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_get_selection_rects() -> *mut u8 {
|
pub extern "C" fn text_editor_get_selection_rects() -> *mut u8 {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return std::ptr::null_mut();
|
return std::ptr::null_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -818,10 +831,6 @@ pub extern "C" fn text_editor_update_blink(timestamp_ms: f64) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_render_overlay() {
|
pub extern "C" fn text_editor_render_overlay() {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(shape_id) = state.text_editor_state.active_shape_id else {
|
let Some(shape_id) = state.text_editor_state.active_shape_id else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@ -858,7 +867,7 @@ pub extern "C" fn text_editor_render_overlay() {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_export_content() -> *mut u8 {
|
pub extern "C" fn text_editor_export_content() -> *mut u8 {
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return std::ptr::null_mut();
|
return std::ptr::null_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -901,7 +910,7 @@ pub extern "C" fn text_editor_export_content() -> *mut u8 {
|
|||||||
pub extern "C" fn text_editor_export_selection() -> *mut u8 {
|
pub extern "C" fn text_editor_export_selection() -> *mut u8 {
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.has_focus {
|
||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
}
|
}
|
||||||
let Some(shape_id) = state.text_editor_state.active_shape_id else {
|
let Some(shape_id) = state.text_editor_state.active_shape_id else {
|
||||||
@ -976,10 +985,10 @@ pub extern "C" fn text_editor_export_selection() -> *mut u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn text_editor_get_selection(buffer_ptr: *mut u32) -> u32 {
|
pub extern "C" fn text_editor_get_selection(buffer_ptr: *mut u32) -> bool {
|
||||||
with_state!(state, {
|
with_state!(state, {
|
||||||
if !state.text_editor_state.is_active {
|
if !state.text_editor_state.selection.is_selection() {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
let sel = &state.text_editor_state.selection;
|
let sel = &state.text_editor_state.selection;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -988,7 +997,7 @@ pub extern "C" fn text_editor_get_selection(buffer_ptr: *mut u32) -> u32 {
|
|||||||
*buffer_ptr.add(2) = sel.focus.paragraph as u32;
|
*buffer_ptr.add(2) = sel.focus.paragraph as u32;
|
||||||
*buffer_ptr.add(3) = sel.focus.offset as u32;
|
*buffer_ptr.add(3) = sel.focus.offset as u32;
|
||||||
}
|
}
|
||||||
1
|
true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user