-
Notifications
You must be signed in to change notification settings - Fork 52
[201_63] 文字选中悬浮窗口实现 #2674
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[201_63] 文字选中悬浮窗口实现 #2674
Changes from all commits
1946632
be002ca
d98f410
027b9f3
a07c958
be4ebe1
e9964b7
3206c1b
a0461ab
4691fb5
25fc892
440c206
b6ba8f9
42de5b0
9c63a7b
082549a
dd0fae7
5a0eedf
0f7afe9
b2266de
3c23f04
bcd1591
fada47d
26e2dd5
fa33eed
fa98913
25d175b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| ;; | ||
| ;; MODULE : text-toolbar.scm | ||
| ;; DESCRIPTION : text selection toolbar icons | ||
| ;; COPYRIGHT : (C) 2026 | ||
| ;; | ||
| ;; This software falls under the GNU general public license version 3 or later. | ||
| ;; It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE | ||
| ;; in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>. | ||
| ;; | ||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
|
|
||
| (texmacs-module (generic text-toolbar) | ||
| (:use (generic format-edit) | ||
| (generic format-menu) | ||
| (generic generic-edit))) | ||
|
|
||
| (menu-bind text-toolbar-icons | ||
| ((balloon (icon "tm_bold.xpm") "Write bold text") | ||
| (toggle-bold)) | ||
| ((balloon (icon "tm_italic.xpm") "Write italic text") | ||
| (toggle-italic)) | ||
| ((balloon (icon "tm_underline.xpm") "Write underline") | ||
| (toggle-underlined)) | ||
| ((balloon (icon "tm_marked.svg") "Marked text") | ||
| (mark-text)) | ||
| (=> (balloon (icon "tm_color.xpm") "Select a foreground color") | ||
| (link color-menu)) | ||
| (=> (balloon (icon "tm_section.xpm") "chapter::menu") | ||
| (link chapter-menu)) | ||
| (=> (balloon (icon "tm_theorem.xpm") "enunciation") | ||
| (link enunciation-menu)) | ||
| ((balloon (icon "left-align.xpm") "left aligned") | ||
| (make-line-with "par-mode" "left")) | ||
| ((balloon (icon "middle-align.xpm") "center") | ||
| (make-line-with "par-mode" "center")) | ||
| ((balloon (icon "right-align.xpm") "right aligned") | ||
| (make-line-with "par-mode" "right"))) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # [201_63] 文字选中悬浮窗口初步实现 | ||
|
|
||
| ## 如何测试 | ||
| 1. 输入一段文字通过键盘或鼠标选中,会出现悬浮窗口 | ||
| 2. 依次点击悬浮窗口按钮,实现的功能和模式工具栏一致 | ||
| 3. 窗口位置的优先级应该是选区顶部>选区底部>窗口中央 | ||
| 4. 切换标签页不会导致原标签页的文本选中窗口失效 | ||
| 5. 单独选中任意数学公式环境该悬浮窗口都不出现,选中公式文本混合内容悬浮窗口出现 | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -21,6 +21,7 @@ | |||||
| #include "path.hpp" | ||||||
| #include "qapplication.h" | ||||||
| #include "qnamespace.h" | ||||||
| #include "qt_simple_widget.hpp" | ||||||
| #include "scheme.hpp" | ||||||
| #include "sys_utils.hpp" | ||||||
| #include "tm_buffer.hpp" | ||||||
|
|
@@ -780,10 +781,14 @@ edit_interface_rep::mouse_any (string type, SI x, SI y, int mods, time_t t, | |||||
| show_image_popup (tree_of_image_parent, selr, magf, get_scroll_x (), | ||||||
| get_scroll_y (), get_canvas_x (), get_canvas_y ()); | ||||||
| } | ||||||
| hide_text_toolbar (); | ||||||
| } | ||||||
| else { | ||||||
| set_cursor_style ("normal"); | ||||||
| hide_image_popup (); | ||||||
|
|
||||||
| // 检查是否应该显示文本工具栏 | ||||||
| update_text_toolbar (); | ||||||
| } | ||||||
|
|
||||||
| if (type == "move") mouse_message ("move", x, y); | ||||||
|
|
@@ -879,10 +884,14 @@ edit_interface_rep::mouse_any (string type, SI x, SI y, int mods, time_t t, | |||||
| if (type == "press-up") mouse_scroll (x, y, true); | ||||||
| if (type == "press-down") mouse_scroll (x, y, false); | ||||||
|
|
||||||
| if ((type == "press-left") || (type == "release-left") || | ||||||
| (type == "end-drag-left") || (type == "press-middle") || | ||||||
| (type == "press-right")) | ||||||
| if ((type == "press-left") || (type == "press-middle") || | ||||||
| (type == "press-right")) { | ||||||
| // 当用户点击其他地方(不在文本工具栏内)时,隐藏文本工具栏 | ||||||
| if (!is_point_in_text_toolbar (x, y)) { | ||||||
| hide_text_toolbar (); | ||||||
| } | ||||||
| notify_change (THE_DECORATIONS); | ||||||
| } | ||||||
|
|
||||||
| if (type == "wheel" && N (data) == 2) | ||||||
| eval ("(wheel-event " * as_string (data[0]) * " " * as_string (data[1]) * | ||||||
|
|
@@ -1014,3 +1023,113 @@ edit_interface_rep::handle_mouse (string kind, SI x, SI y, int m, time_t t, | |||||
| } | ||||||
| handle_exceptions (); | ||||||
| } | ||||||
|
|
||||||
| /****************************************************************************** | ||||||
| * Text toolbar support | ||||||
| ******************************************************************************/ | ||||||
|
|
||||||
| bool | ||||||
| edit_interface_rep::should_show_text_toolbar () { | ||||||
| if (as_bool (call ("in-math?")) || as_bool (call ("in-prog?")) || | ||||||
| as_bool (call ("in-code?")) || as_bool (call ("in-verbatim?"))) | ||||||
| return false; | ||||||
| // 检查是否有活动的文本选区 | ||||||
| if (!selection_active_any ()) return false; | ||||||
|
|
||||||
| // 检查选区是否非空 | ||||||
| tree sel_tree= selection_get (); | ||||||
| if (is_atomic (sel_tree) && as_string (sel_tree) == "") return false; | ||||||
|
|
||||||
| return true; | ||||||
| } | ||||||
|
|
||||||
| rectangle | ||||||
| edit_interface_rep::get_text_selection_rect () { | ||||||
| rectangle sel_rect; | ||||||
|
|
||||||
| if (selection_active_any () && !is_nil (selection_rects)) { | ||||||
| // 使用现有的选区矩形 | ||||||
| sel_rect= least_upper_bound (selection_rects); | ||||||
| } | ||||||
| else if (selection_active_any ()) { | ||||||
| // 如果没有选区矩形,但选区存在,计算一个默认矩形 | ||||||
| path p1, p2; | ||||||
| selection_get (p1, p2); | ||||||
| if (p1 != p2) { | ||||||
| selection sel= search_selection (p1, p2); | ||||||
| if (!is_nil (sel->rs)) { | ||||||
| sel_rect= least_upper_bound (sel->rs); | ||||||
| } | ||||||
| else { | ||||||
| // 如果选区矩形为空,使用光标位置创建一个最小矩形 | ||||||
| cursor cu= get_cursor (); | ||||||
| sel_rect = rectangle (cu->ox - 10 * pixel, cu->oy - 5 * pixel, | ||||||
| cu->ox + 10 * pixel, cu->oy + 5 * pixel); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| return sel_rect; | ||||||
| } | ||||||
|
Comment on lines
+1046
to
+1073
|
||||||
|
|
||||||
| void | ||||||
| edit_interface_rep::show_text_toolbar (rectangle selr, double magf, | ||||||
| int scroll_x, int scroll_y, int canvas_x, | ||||||
| int canvas_y) { | ||||||
| // 通过qt_simple_widget显示文本工具栏 | ||||||
| // this指针实际上是edit_interface_rep,它继承自editor_rep,而editor_rep继承自simple_widget_rep | ||||||
| // 在Qt环境下,simple_widget_rep实际上是qt_simple_widget_rep | ||||||
| qt_simple_widget_rep* qsw= static_cast<qt_simple_widget_rep*> (this); | ||||||
| qsw->show_text_toolbar (selr, magf, scroll_x, scroll_y, canvas_x, canvas_y); | ||||||
| } | ||||||
|
|
||||||
| void | ||||||
| edit_interface_rep::hide_text_toolbar () { | ||||||
| // 通过qt_simple_widget隐藏文本工具栏 | ||||||
| qt_simple_widget_rep* qsw= static_cast<qt_simple_widget_rep*> (this); | ||||||
| qsw->hide_text_toolbar (); | ||||||
| } | ||||||
|
|
||||||
| bool | ||||||
| edit_interface_rep::is_point_in_text_toolbar (SI x, SI y) { | ||||||
| // 通过qt_simple_widget检查点是否在文本工具栏内 | ||||||
| qt_simple_widget_rep* qsw= static_cast<qt_simple_widget_rep*> (this); | ||||||
| return qsw->is_point_in_text_toolbar (x, y); | ||||||
| } | ||||||
|
|
||||||
| void | ||||||
| edit_interface_rep::update_text_toolbar () { | ||||||
| if (left_dragging) { | ||||||
| hide_text_toolbar (); | ||||||
| return; | ||||||
| } | ||||||
| // 检查是否应该显示文本工具栏 | ||||||
| if (should_show_text_toolbar ()) { | ||||||
| rectangle text_selr= get_text_selection_rect (); | ||||||
| // 检查矩形是否有效(非零面积) | ||||||
| // 注意:rectangle 不是 list 类型,不能使用 is_nil | ||||||
| // 我们检查矩形坐标是否有效 | ||||||
| if (text_selr->x1 < text_selr->x2 && text_selr->y1 < text_selr->y2) { | ||||||
| update_visible (); | ||||||
| SI sel_x1= min (text_selr->x1, text_selr->x2); | ||||||
| SI sel_x2= max (text_selr->x1, text_selr->x2); | ||||||
| SI sel_y1= min (text_selr->y1, text_selr->y2); | ||||||
| SI sel_y2= max (text_selr->y1, text_selr->y2); | ||||||
| bool sel_in_view= | ||||||
| !(sel_x2 < vx1 || sel_x1 > vx2 || sel_y2 < vy1 || sel_y1 > vy2); | ||||||
| if (!sel_in_view) { | ||||||
| hide_text_toolbar (); | ||||||
| return; | ||||||
| } | ||||||
| show_text_toolbar (text_selr, magf, get_scroll_x (), get_scroll_y (), | ||||||
| get_canvas_x (), get_canvas_y ()); | ||||||
| } | ||||||
| else { | ||||||
| // 即使矩形无效,也尝试显示工具栏(例如单个字符选区) | ||||||
|
||||||
| // 即使矩形无效,也尝试显示工具栏(例如单个字符选区) | |
| // 如果矩形无效,则隐藏工具栏(例如单个字符选区尚未形成有效矩形时) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个是出于什么目的?那代码块是不是也要判断 🤔