Compare commits

...

23 commits

Author SHA1 Message Date
936e57b63e chore: fige Cargo.lock (epoch-1.9.0, [patch] locaux)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 21:03:54 +02:00
c45b23aa85 merge: epoch-1.9.0 d'upstream
# Conflicts:
#	Cargo.lock
2026-09-24 20:50:47 +02:00
Hojjat
bfc98bf219 chore: update libcosmic to fix esc, and bindings in context menu 2026-09-23 11:30:54 -06:00
Michael Aaron Murphy
14aba66228 chore: update debian/rules 2026-09-16 16:28:59 -04:00
Michael Aaron Murphy
430120f6ff chore: update cosmic-files and libcosmic 2026-09-16 16:28:59 -04:00
Hojjat
9307793661 feat: use libcosmic's context_menu widget 2026-09-16 16:28:59 -04:00
Hojjat
505ecd18fe chore: adopt typed surface actions from libcosmic 2026-09-16 16:28:59 -04:00
Michael Aaron Murphy
4b4871ecf4 Epoch 1.9.0 version update
Generated by cosmic-epoch scripts/version-update.sh
2026-09-16 16:28:59 -04:00
Michael Murphy
1054b6a7fd
i18n: translation update from Hosted Weblate (#616)
Translations update from [Hosted Weblate](https://hosted.weblate.org)
for [Pop OS/COSMIC
Edit](https://hosted.weblate.org/projects/pop-os/cosmic-edit/).



Current translation status:

![Weblate translation
status](https://hosted.weblate.org/widget/pop-os/cosmic-edit/matrix-auto.svg)
2026-09-15 21:56:46 +02:00
Hosted Weblate
139cfaaf5c
i18n: translation updates from weblate
Co-authored-by: Amadɣas <massiin@proton.me>
Co-authored-by: Blauen <butterflee555@gmail.com>
Co-authored-by: CYAXXX <85353920+CYAXXX@users.noreply.github.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kurt Harren Catindig <kurtharrencatindig03@gmail.com>
Co-authored-by: Quentin PAGÈS <quentinantonin@free.fr>
Co-authored-by: Satakun Utama <galaxytomostore@gmail.com>
Co-authored-by: VandaL <vandalhj@gmail.com>
Co-authored-by: therealmate <hellogaming91@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-edit/hu/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-edit/kab/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-edit/kmr/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-edit/oc/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-edit/pl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-edit/th/
Translation: Pop OS/COSMIC Edit
2026-09-13 01:54:35 +02:00
85da7f90f2 chore: fige Cargo.lock 2026-09-10 18:12:37 +02:00
70c1765b1f Merge tag 'epoch-1.8.0' into local/libcosmic-path-patch
Epoch 1.8.0

# Conflicts:
#	Cargo.lock
2026-09-10 17:57:28 +02:00
20c47377a8 chore: fige Cargo.lock (reordonnancement patch.unused par cargo) 2026-09-04 10:48:53 +02:00
Jeremy Soller
26f6ffd3e6 Epoch 1.8.0 version update
Generated by cosmic-epoch scripts/version-update.sh
2026-09-03 13:18:38 -06:00
6150549a9b chore: fige Cargo.lock tel que resolu apres le merge 1.7.0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 07:58:51 +02:00
de9ae6890a Merge tag 'epoch-1.7.0' into local/libcosmic-path-patch
Epoch 1.7.0
2026-08-27 07:50:01 +02:00
Jeremy Soller
13b1d4aac0 Epoch 1.7.0 version update
Generated by cosmic-epoch scripts/version-update.sh
2026-08-25 11:39:01 -06:00
Michael Murphy
6c800ce1f1
i18n: translation update from Hosted Weblate (#610)
Translations update from [Hosted Weblate](https://hosted.weblate.org)
for [Pop OS/COSMIC
Edit](https://hosted.weblate.org/projects/pop-os/cosmic-edit/).



Current translation status:

![Weblate translation
status](https://hosted.weblate.org/widget/pop-os/cosmic-edit/matrix-auto.svg)
2026-08-24 20:52:37 +02:00
Jeremy Soller
0e9c927f1a
Fix tab auto focus on TabCloseForce (#603)
Auto focus should only trigger if the current tab is selected or else
closing an unfocused tab would move the focused tab.

See: pop-os/cosmic-files#1949

- [x] I have disclosed use of any AI generated code in my commit
messages.
- If you are using an LLM, and do not fully understand the changes it is
making to the code base, do not create a PR.
- In our experience, AI generated code often results in overly complex
code that lacks enough context for a proper fix or feature inclusion.
This results in considerably longer code reviews. Due to this, AI
authored or partially authored PRs may be closed without comment.
- [x] I understand these changes in full and will be able to respond to
review comments.
- [x] My change is accurately described in the commit message.
- [x] My contribution is tested and working as described.
- [x] I have read the [Developer Certificate of
Origin](https://developercertificate.org/) and certify my contribution
under its conditions.
2026-08-20 19:02:21 -06:00
Jeremy Soller
b23384043e
feat: disable Cut and Copy buttons when no text is selected (#588)
- [x] I have disclosed use of any AI generated code in my commit
messages.
- If you are using an LLM, and do not fully understand the changes it is
making to the code base, do not create a PR.
- In our experience, AI generated code often results in overly complex
code that lacks enough context for a proper fix or feature inclusion.
This results in considerably longer code reviews. Due to this, AI
authored or partially authored PRs may be closed without comment.
- [x] I understand these changes in full and will be able to respond to
review comments.
- [x] My change is accurately described in the commit message.
- [x] My contribution is tested and working as described.
- [x] I have read the [Developer Certificate of
Origin](https://developercertificate.org/) and certify my contribution
under its conditions.
2026-08-20 19:01:35 -06:00
Hosted Weblate
4a5be62b02
i18n: translation updates from weblate
Co-authored-by: Jens Peter Nielsen <mail@jp-nielsen.dk>
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-edit/da/
Translation: Pop OS/COSMIC Edit
2026-08-19 09:52:58 +00:00
nicole mikołajczyk
8c9c15de85 feat: disable Cut and Copy buttons when no text is selected
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2026-08-18 15:49:12 -06:00
Josh Megnauth
e4006945c6
Fix tab auto focus on TabCloseForce
Auto focus should only trigger if the current tab is selected or else
closing an unfocused tab would move the focused tab.

See: pop-os/cosmic-files#1949
2026-08-01 20:11:53 -04:00
17 changed files with 541 additions and 685 deletions

959
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
[package] [package]
name = "cosmic-edit" name = "cosmic-edit"
version = "1.6.0" version = "1.9.0"
authors = ["Jeremy Soller <jeremy@system76.com>"] authors = ["Jeremy Soller <jeremy@system76.com>"]
edition = "2024" edition = "2024"
license = "GPL-3.0-only" license = "GPL-3.0-only"

18
debian/changelog vendored
View file

@ -1,3 +1,21 @@
cosmic-edit (1.9.0) noble; urgency=medium
* Epoch 1.9.0 version update
-- Michael Murphy <michael@mmurphy.dev> Mon, 14 Sep 2026 21:54:06 +0200
cosmic-edit (1.8.0) noble; urgency=medium
* Epoch 1.8.0 version update
-- Jeremy Soller <jeremy@system76.com> Wed, 02 Sep 2026 08:14:30 -0600
cosmic-edit (1.7.0) noble; urgency=medium
* Epoch 1.7.0 version update
-- Jeremy Soller <jeremy@system76.com> Tue, 25 Aug 2026 09:19:59 -0600
cosmic-edit (1.6.0) noble; urgency=medium cosmic-edit (1.6.0) noble; urgency=medium
* Epoch 1.6.0 version update * Epoch 1.6.0 version update

5
debian/rules vendored
View file

@ -1,15 +1,12 @@
#!/usr/bin/make -f #!/usr/bin/make -f
export DESTDIR = debian/cosmic-edit export DESTDIR = debian/cosmic-edit
export VENDOR ?= 1
%: %:
dh $@ dh $@
override_dh_auto_clean: override_dh_auto_clean:
if ! ischroot && test "${VENDOR}" = "1"; then \ ischroot || just vendor
just vendor; \
fi
override_dh_auto_build: override_dh_auto_build:
just build-vendored just build-vendored

View file

@ -1,4 +1,6 @@
tar-ignore=.github tar-ignore=.github
tar-ignore=.vscode tar-ignore=target/.rustc_info.json
tar-ignore=target/CACHEDIR.TAG
tar-ignore=target/debug
tar-ignore=target/release
tar-ignore=vendor tar-ignore=vendor
tar-ignore=target

View file

@ -1,5 +1,5 @@
save = Gem save = Gem
cancel = Annuller cancel = Afbryd
quit = Afslut quit = Afslut
cosmic-text-editor = COSMIC-teksteditor cosmic-text-editor = COSMIC-teksteditor
new-document = Nyt dokument new-document = Nyt dokument

0
i18n/fil/cosmic_edit.ftl Normal file
View file

View file

@ -60,7 +60,7 @@ default-zoom-step = Nagyítási mérték
### Keyboard shortcuts ### Keyboard shortcuts
keyboard-shortcuts = Gyorsbillentyűk keyboard-shortcuts = Gyorsbillentyűk
enable-vim-bindings = Vim billentyűkombinációk engedélyezése enable-vim-bindings = Vim-billentyűkombinációk engedélyezése
# Find # Find
find-placeholder = Keresés… find-placeholder = Keresés…
find-previous = Előző találat find-previous = Előző találat

View file

@ -1,9 +1,9 @@
cancel = Sefsex cancel = Semmet
undo = Ssemmet undo = Ssemmet
save = Sekles save = Sekles
quit = Tuffɣa quit = Ffeɣ
replace = Semselsi replace = Semselsi
support = Tallalt support = Tallelt
settings = Iɣewwaṛen settings = Iɣewwaṛen
appearance = Timeẓri appearance = Timeẓri
theme = Asentel theme = Asentel
@ -16,7 +16,7 @@ default-size = Tiddi tamezwert
zoom-out = Asemẓi zoom-out = Asemẓi
view = Wali view = Wali
menu-settings = Iɣewwaṛen… menu-settings = Iɣewwaṛen…
match-desktop = Amṣada d tnarit match-desktop = Semṣada akked tnarit
file = Afaylu file = Afaylu
new-window = Asfaylu amaynut new-window = Asfaylu amaynut
edit = Ẓreg edit = Ẓreg

View file

@ -12,7 +12,7 @@ support = Piştgirî
quit = Biqedîne quit = Biqedîne
find-placeholder = Bibîne... find-placeholder = Bibîne...
copy = Jê bigire copy = Jê bigire
paste = Pêve bike paste = Pê ve bike
match-desktop = Bi sermaseyê re li hev bîne match-desktop = Bi sermaseyê re li hev bîne
select-all = Hemûyan hilbijêre select-all = Hemûyan hilbijêre
zoom-in = Nêzîk bike zoom-in = Nêzîk bike

View file

@ -1,8 +1,13 @@
settings = Paramètres settings = Configuracion
appearance = Aparéncia appearance = Aparéncia
theme = Tèma theme = Tèma
match-desktop = Assortir al burèu match-desktop = Assortir al burèu
dark = Fosc dark = Escur
light = Clar light = Clar
file = Fichièr file = Fichièr
close-file = Tampar lo fichièr close-file = Tampar lo fichièr
cancel = Anullar
repository = Depaus
menu-settings = Configuracion...
quit = Quitar
replace = Remplaçar

View file

@ -1,5 +1,5 @@
cosmic-text-editor = Edytor Tekstu COSMIC cosmic-text-editor = Edytor Tekstu COSMIC
comment = Edytor tekstu pulpitu COSMIC comment = Edytor tekstu dla środowiska COSMIC
new-document = Nowy dokument new-document = Nowy dokument
open-project = Otwórz projekt open-project = Otwórz projekt
todo = TODO todo = TODO
@ -64,7 +64,7 @@ default-zoom-step = Stopniowanie powiększania
keyboard-shortcuts = Skróty klawiszowe keyboard-shortcuts = Skróty klawiszowe
enable-vim-bindings = Włącz tryb Vim enable-vim-bindings = Włącz tryb Vim
# Find # Find
find-placeholder = Szukaj… find-placeholder = Wyszukaj…
find-previous = Znajdź poprzedni find-previous = Znajdź poprzedni
find-next = Znajdź następny find-next = Znajdź następny
replace-placeholder = Zastąp… replace-placeholder = Zastąp…
@ -106,8 +106,8 @@ cut = Wytnij
copy = Kopiuj copy = Kopiuj
paste = Wklej paste = Wklej
select-all = Zaznacz wszystko select-all = Zaznacz wszystko
find = Szukaj find = Wyszukaj
find-in-project = Szukaj w projekcie… find-in-project = Wyszukaj w projekcie…
spell-check = Sprawdź ortografię… spell-check = Sprawdź ortografię…
## View ## View

View file

@ -0,0 +1,6 @@
cancel = ยกเลิก
settings = การตั้งค่า
dark = มืด
light = สว่าง
replace = แทนที่
appearance = ลักษณะ

View file

@ -11,7 +11,7 @@ use cosmic::{
cosmic_theme, executor, cosmic_theme, executor,
font::Font, font::Font,
iced::{ iced::{
self, Alignment, Background, Color, Length, Limits, Point, Subscription, self, Alignment, Background, Color, Length, Limits, Subscription,
advanced::graphics::text::font_system, advanced::graphics::text::font_system,
clipboard, event, clipboard, event,
futures::{self, SinkExt}, futures::{self, SinkExt},
@ -194,6 +194,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum Action { pub enum Action {
Todo, Todo,
NoOp,
About, About,
CloseFile, CloseFile,
CloseProject(usize), CloseProject(usize),
@ -244,6 +245,7 @@ impl Action {
fn message(&self, entity_opt: Option<Entity>) -> Message { fn message(&self, entity_opt: Option<Entity>) -> Message {
match self { match self {
Self::Todo => Message::Todo, Self::Todo => Message::Todo,
Self::NoOp => Message::NoOp,
Self::About => Message::ToggleContextPage(ContextPage::About), Self::About => Message::ToggleContextPage(ContextPage::About),
Self::CloseFile => Message::CloseFile, Self::CloseFile => Message::CloseFile,
Self::CloseProject(project_i) => Message::CloseProject(*project_i), Self::CloseProject(project_i) => Message::CloseProject(*project_i),
@ -371,6 +373,7 @@ pub enum Message {
Modifiers(Modifiers), Modifiers(Modifiers),
NewFile, NewFile,
NewWindow, NewWindow,
NoOp,
NotifyEvent(notify::Event), NotifyEvent(notify::Event),
NotifyWatcher(WatcherWrapper), NotifyWatcher(WatcherWrapper),
OpenFile(PathBuf), OpenFile(PathBuf),
@ -400,7 +403,7 @@ pub enum Message {
SaveAsResult(segmented_button::Entity, DialogResult), SaveAsResult(segmented_button::Entity, DialogResult),
Scroll(f32), Scroll(f32),
SelectAll, SelectAll,
Surface(surface::Action), Surface(surface::Action<Message>),
SystemThemeModeChange(cosmic_theme::ThemeMode), SystemThemeModeChange(cosmic_theme::ThemeMode),
SyntaxTheme(usize, bool), SyntaxTheme(usize, bool),
TabActivate(segmented_button::Entity), TabActivate(segmented_button::Entity),
@ -409,7 +412,7 @@ pub enum Message {
TabClose(segmented_button::Entity), TabClose(segmented_button::Entity),
TabCloseForce(segmented_button::Entity), TabCloseForce(segmented_button::Entity),
TabContextAction(segmented_button::Entity, Action), TabContextAction(segmented_button::Entity, Action),
TabContextMenu(segmented_button::Entity, Option<Point>), TabContextMenu(segmented_button::Entity, bool),
TabNext, TabNext,
TabPrev, TabPrev,
TabSetCursor(segmented_button::Entity, Cursor), TabSetCursor(segmented_button::Entity, Cursor),
@ -2162,6 +2165,9 @@ impl Application for App {
} }
} }
} }
Message::NoOp => {
// Do nothing
}
Message::NotifyEvent(event) => { Message::NotifyEvent(event) => {
// Reload tabs that changed // Reload tabs that changed
let mut tab_reload = Vec::new(); let mut tab_reload = Vec::new();
@ -2707,9 +2713,7 @@ impl Application for App {
} }
} }
Message::Surface(a) => { Message::Surface(a) => {
return cosmic::task::message(cosmic::Action::Cosmic( return cosmic::task::message(cosmic::Action::Surface(a));
cosmic::app::Action::Surface(a),
));
} }
Message::SystemThemeModeChange(_theme_mode) => { Message::SystemThemeModeChange(_theme_mode) => {
return self.update_config(); return self.update_config();
@ -2788,7 +2792,9 @@ impl Application for App {
} }
Message::TabCloseForce(entity) => { Message::TabCloseForce(entity) => {
// Activate closest item // Activate closest item
if let Some(position) = self.tab_model.position(entity) { if self.tab_model.active() == entity
&& let Some(position) = self.tab_model.position(entity)
{
if position > 0 { if position > 0 {
self.tab_model.activate_position(position - 1); self.tab_model.activate_position(position - 1);
} else { } else {
@ -2815,15 +2821,15 @@ impl Application for App {
Message::TabContextAction(entity, action) => { Message::TabContextAction(entity, action) => {
if let Some(Tab::Editor(tab)) = self.tab_model.data_mut::<Tab>(entity) { if let Some(Tab::Editor(tab)) = self.tab_model.data_mut::<Tab>(entity) {
// Close context menu // Close context menu
tab.context_menu = None; tab.context_menu_open = false;
// Run action's message // Run action's message
return self.update(action.message(None)); return self.update(action.message(None));
} }
} }
Message::TabContextMenu(entity, position_opt) => { Message::TabContextMenu(entity, open) => {
if let Some(Tab::Editor(tab)) = self.tab_model.data_mut::<Tab>(entity) { if let Some(Tab::Editor(tab)) = self.tab_model.data_mut::<Tab>(entity) {
// Update context menu // Update context menu
tab.context_menu = position_opt; tab.context_menu_open = open;
} }
} }
Message::TabNext => { Message::TabNext => {
@ -3028,12 +3034,19 @@ impl Application for App {
} }
fn header_start(&self) -> Vec<Element<'_, Message>> { fn header_start(&self) -> Vec<Element<'_, Message>> {
let has_selection = match self.active_tab() {
Some(Tab::Editor(tab)) => tab.editor.lock().unwrap().selection() != Selection::None,
Some(Tab::GitDiff(_)) => false,
None => false,
};
vec![menu_bar( vec![menu_bar(
&self.core, &self.core,
&self.config, &self.config,
&self.config_state, &self.config_state,
&self.key_binds, &self.key_binds,
&self.projects, &self.projects,
has_selection,
)] )]
} }
@ -3078,23 +3091,25 @@ impl Application for App {
.on_focus(Message::FindFocused(false)) .on_focus(Message::FindFocused(false))
.on_auto_scroll(Message::AutoScroll) .on_auto_scroll(Message::AutoScroll)
.on_changed(Message::TabChanged(tab_id)) .on_changed(Message::TabChanged(tab_id))
.has_context_menu(tab.context_menu.is_some()) .has_context_menu(tab.context_menu_open)
.on_context_menu(move |position_opt| { .on_context_menu(move |open| Message::TabContextMenu(tab_id, open));
Message::TabContextMenu(tab_id, position_opt)
});
if self.config.highlight_current_line { if self.config.highlight_current_line {
text_box = text_box.highlight_current_line(); text_box = text_box.highlight_current_line();
} }
if self.config.line_numbers { if self.config.line_numbers {
text_box = text_box.line_numbers(); text_box = text_box.line_numbers();
} }
let mut popover = widget::popover(text_box); let has_selection = tab.editor.lock().unwrap().selection() != Selection::None;
if let Some(point) = tab.context_menu { let mut context_menu = widget::context_menu(
popover = popover text_box,
.popup(menu::context_menu(&self.key_binds, tab_id)) Some(menu::context_menu(&self.key_binds, tab_id, has_selection)),
.position(widget::popover::Position::Point(point)); )
.on_close(Message::TabContextMenu(tab_id, false))
.on_surface_action(Message::Surface);
if let Some(window_id) = self.core().main_window_id() {
context_menu = context_menu.window_id(window_id);
} }
tab_column = tab_column.push(popover); tab_column = tab_column.push(context_menu);
if self.config.vim_bindings { if self.config.vim_bindings {
let status = { let status = {
let editor = tab.editor.lock().unwrap(); let editor = tab.editor.lock().unwrap();

View file

@ -1,18 +1,15 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use cosmic::widget::menu::Item as MenuItem; use cosmic::widget::menu::Item as MenuItem;
use cosmic::widget::menu::action::MenuAction;
use cosmic::widget::menu::key_bind::KeyBind; use cosmic::widget::menu::key_bind::KeyBind;
use cosmic::{ use cosmic::{
Element, Element,
app::Core, app::Core,
iced::{
Background, Border, Length, advanced::widget::text::Style as TextStyle, widget::column,
},
theme,
widget::{ widget::{
self, divider, self,
menu::{ItemHeight, ItemWidth, menu_button}, menu::{ItemHeight, ItemWidth},
responsive_menu_bar, segmented_button, space, responsive_menu_bar, segmented_button,
}, },
}; };
use std::{collections::HashMap, path::PathBuf, sync::LazyLock}; use std::{collections::HashMap, path::PathBuf, sync::LazyLock};
@ -116,68 +113,49 @@ fn format_recent_menu_path(path: &PathBuf, home_dir_opt: Option<&PathBuf>) -> St
truncate_middle(&display, RECENT_MENU_LABEL_MAX_CHARS) truncate_middle(&display, RECENT_MENU_LABEL_MAX_CHARS)
} }
pub fn context_menu<'a>( /// A context menu action dispatched to the tab the menu was opened on.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct TabAction(pub segmented_button::Entity, pub Action);
impl MenuAction for TabAction {
type Message = Message;
fn message(&self) -> Message {
Message::TabContextAction(self.0, self.1)
}
}
pub fn context_menu(
key_binds: &HashMap<KeyBind, Action>, key_binds: &HashMap<KeyBind, Action>,
entity: segmented_button::Entity, entity: segmented_button::Entity,
) -> Element<'a, Message> { has_selection: bool,
fn key_style(theme: &cosmic::Theme) -> TextStyle { ) -> Vec<widget::menu::Tree<Message>> {
// TODO use wayland popups let item =
let mut color = theme.cosmic().background(false).component.on; |label: String, action: Action| MenuItem::Button(label, None, TabAction(entity, action));
color.alpha *= 0.75; let optional = |label: String, action: Action, enabled: bool| {
TextStyle { if enabled {
color: Some(color.into()), MenuItem::Button(label, None, TabAction(entity, action))
..Default::default() } else {
MenuItem::ButtonDisabled(label, None, TabAction(entity, action))
} }
}
let menu_item = |menu_label, menu_action| {
let mut key = String::new();
for (key_bind, key_action) in key_binds.iter() {
if key_action == &menu_action {
key = key_bind.to_string();
break;
}
}
menu_button(vec![
widget::text(menu_label).into(),
space::horizontal().into(),
widget::text(key)
.class(theme::Text::Custom(key_style))
.into(),
])
.on_press(Message::TabContextAction(entity, menu_action))
}; };
widget::container( let key_binds: HashMap<KeyBind, TabAction> = key_binds
cosmic::widget::menu::menu_column::MenuColumn::with_children([ .iter()
menu_item(fl!("undo"), Action::Undo).into(), .map(|(key_bind, action)| (key_bind.clone(), TabAction(entity, *action)))
menu_item(fl!("redo"), Action::Redo).into(), .collect();
divider::horizontal::light().into(), widget::menu::items(
menu_item(fl!("cut"), Action::Cut).into(), &key_binds,
menu_item(fl!("copy"), Action::Copy).into(), vec![
menu_item(fl!("paste"), Action::Paste).into(), item(fl!("undo"), Action::Undo),
menu_item(fl!("select-all"), Action::SelectAll).into(), item(fl!("redo"), Action::Redo),
]), MenuItem::Divider,
optional(fl!("cut"), Action::Cut, has_selection),
optional(fl!("copy"), Action::Copy, has_selection),
item(fl!("paste"), Action::Paste),
item(fl!("select-all"), Action::SelectAll),
],
) )
.padding(1)
//TODO: move style to libcosmic
.style(|theme| {
let cosmic = theme.cosmic();
let component = &cosmic.background(false).component;
widget::container::Style {
icon_color: Some(component.on.into()),
text_color: Some(component.on.into()),
background: Some(Background::Color(component.base.into())),
border: Border {
radius: cosmic.radius_s().map(|x| x + 1.0).into(),
width: 1.0,
color: component.divider.into(),
},
..Default::default()
}
})
.width(Length::Fixed(240.0))
.into()
} }
pub fn menu_bar<'a>( pub fn menu_bar<'a>(
@ -186,6 +164,7 @@ pub fn menu_bar<'a>(
config_state: &ConfigState, config_state: &ConfigState,
key_binds: &HashMap<KeyBind, Action>, key_binds: &HashMap<KeyBind, Action>,
projects: &Vec<(String, PathBuf)>, projects: &Vec<(String, PathBuf)>,
has_selection: bool,
) -> Element<'a, Message> { ) -> Element<'a, Message> {
//TODO: port to libcosmic //TODO: port to libcosmic
let menu_tab_width = |tab_width: u16| { let menu_tab_width = |tab_width: u16| {
@ -278,8 +257,16 @@ pub fn menu_bar<'a>(
MenuItem::Button(fl!("undo"), None, Action::Undo), MenuItem::Button(fl!("undo"), None, Action::Undo),
MenuItem::Button(fl!("redo"), None, Action::Redo), MenuItem::Button(fl!("redo"), None, Action::Redo),
MenuItem::Divider, MenuItem::Divider,
MenuItem::Button(fl!("cut"), None, Action::Cut), if has_selection {
MenuItem::Button(fl!("copy"), None, Action::Copy), MenuItem::Button(fl!("cut"), None, Action::Cut)
} else {
MenuItem::ButtonDisabled(fl!("cut"), None, Action::NoOp)
},
if has_selection {
MenuItem::Button(fl!("copy"), None, Action::Copy)
} else {
MenuItem::ButtonDisabled(fl!("copy"), None, Action::NoOp)
},
MenuItem::Button(fl!("paste"), None, Action::Paste), MenuItem::Button(fl!("paste"), None, Action::Paste),
MenuItem::Button(fl!("select-all"), None, Action::SelectAll), MenuItem::Button(fl!("select-all"), None, Action::SelectAll),
MenuItem::Divider, MenuItem::Divider,

View file

@ -1,9 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use cosmic::{ use cosmic::{iced::advanced::graphics::text::font_system, widget::icon};
iced::{Point, advanced::graphics::text::font_system},
widget::icon,
};
use cosmic_files::mime_icon::{FALLBACK_MIME_ICON, mime_for_path, mime_icon}; use cosmic_files::mime_icon::{FALLBACK_MIME_ICON, mime_for_path, mime_icon};
use cosmic_text::{Attrs, Buffer, Cursor, Edit, Selection, Shaping, SyntaxEditor, ViEditor, Wrap}; use cosmic_text::{Attrs, Buffer, Cursor, Edit, Selection, Shaping, SyntaxEditor, ViEditor, Wrap};
use regex::Regex; use regex::Regex;
@ -51,7 +48,7 @@ pub struct EditorTab {
pub path_opt: Option<PathBuf>, pub path_opt: Option<PathBuf>,
attrs: Attrs<'static>, attrs: Attrs<'static>,
pub editor: Mutex<ViEditor<'static, 'static>>, pub editor: Mutex<ViEditor<'static, 'static>>,
pub context_menu: Option<Point>, pub context_menu_open: bool,
pub zoom_adj: i8, pub zoom_adj: i8,
} }
@ -75,7 +72,7 @@ impl EditorTab {
path_opt: None, path_opt: None,
attrs, attrs,
editor: Mutex::new(ViEditor::new(editor)), editor: Mutex::new(ViEditor::new(editor)),
context_menu: None, context_menu_open: false,
zoom_adj, zoom_adj,
}; };

View file

@ -51,7 +51,7 @@ pub struct TextBox<'a, Message> {
on_focus: Option<Message>, on_focus: Option<Message>,
click_timing: Duration, click_timing: Duration,
has_context_menu: bool, has_context_menu: bool,
on_context_menu: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>, on_context_menu: Option<Box<dyn Fn(bool) -> Message + 'a>>,
highlight_current_line: bool, highlight_current_line: bool,
line_numbers: bool, line_numbers: bool,
} }
@ -107,10 +107,7 @@ where
self self
} }
pub fn on_context_menu( pub fn on_context_menu(mut self, on_context_menu: impl Fn(bool) -> Message + 'a) -> Self {
mut self,
on_context_menu: impl Fn(Option<Point>) -> Message + 'a,
) -> Self {
self.on_context_menu = Some(Box::new(on_context_menu)); self.on_context_menu = Some(Box::new(on_context_menu));
self self
} }
@ -1267,14 +1264,9 @@ where
// Update context menu state // Update context menu state
if let Some(on_context_menu) = &self.on_context_menu { if let Some(on_context_menu) = &self.on_context_menu {
shell.publish((on_context_menu)(if self.has_context_menu { shell.publish((on_context_menu)(
None !self.has_context_menu && matches!(button, Button::Right),
} else { ));
match button {
Button::Right => Some(p),
_ => None,
}
}));
} }
shell.capture_event(); shell.capture_event();