Compare commits
10 commits
2af316c867
...
23d81bf847
Author | SHA1 | Date | |
---|---|---|---|
23d81bf847 | |||
1febc424a2 | |||
acc2c27770 | |||
c508a18941 | |||
f9a712fea4 | |||
f86a8ab094 | |||
85b2b587c1 | |||
1d13e429ff | |||
d3ed74d3b2 | |||
d0f8c4d7fd |
59
.github/workflows/release.yml
vendored
59
.github/workflows/release.yml
vendored
|
@ -1,59 +0,0 @@
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
actions: read
|
|
||||||
checks: write
|
|
||||||
deployments: write
|
|
||||||
issues: write
|
|
||||||
packages: write
|
|
||||||
pull-requests: write
|
|
||||||
statuses: write
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [created]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: release ${{ matrix.target }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
target:
|
|
||||||
# Temporarily disabling Windows compilation
|
|
||||||
# - x86_64-pc-windows-gnu
|
|
||||||
- x86_64-unknown-linux-musl
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Set up Rust
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: stable
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Install target
|
|
||||||
run: rustup target add ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Check Rust target installation
|
|
||||||
run: rustup target list --installed
|
|
||||||
|
|
||||||
- name: Compile the app
|
|
||||||
run: |
|
|
||||||
echo "Compiling for target: ${{ matrix.target }}"
|
|
||||||
cargo build --release --target ${{ matrix.target }}
|
|
||||||
|
|
||||||
- name: Create tarball
|
|
||||||
run: |
|
|
||||||
release_tag=${{ github.event.release.tag_name }}
|
|
||||||
tar -czvf calcifer_v${release_tag}.tar.gz -C target/${{ matrix.target }}/release calcifer
|
|
||||||
|
|
||||||
- name: Upload release assets
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ github.event.release.upload_url }}
|
|
||||||
asset_path: calcifer_v${{ github.event.release.tag_name }}.tar.gz
|
|
||||||
asset_name: calcifer_v${{ github.event.release.tag_name }}.tar.gz
|
|
||||||
asset_content_type: application/gzip
|
|
|
@ -1 +1 @@
|
||||||
{"categories":[{"name":"to do","content":[{"name":"update workflow .yml","description":"make a workflow compiling the calcifer and put the linux in calcifer-{version}\nand the windows in calcifer_windows_{version}\n\nupdate nix\nupdate jiji","id":5}]},{"name":"in progress","content":[{"name":"export copy paste fix","description":"// Hello there","id":1}]},{"name":"done","content":[{"name":"move .project file","description":"// Hello there","id":4},{"name":"move config","description":"config from .calcifer/save.json\nto .config/calcifer/state.json","id":1},{"name":"add id to textarea per tab","description":"to improve undo, make each code area of each tab have a unique id (no more undo into another tab)","id":1},{"name":"file tree id ?","description":"// Hello there","id":1},{"name":"open dir in tree ?","description":"// Hello there","id":2},{"name":"fix tab title","description":"// Hello there","id":2}]},{"name":"+","content":[]}]}
|
{"categories":[{"name":"to do","content":[{"name":"update workflow .yml","description":"make a workflow compiling the calcifer and put the linux in calcifer-{version}\nand the windows in calcifer_windows_{version}\n\nupdate nix\nupdate jiji","id":5},{"name":"draggable item for project mode","description":"// Hello there","id":2}]},{"name":"in progress","content":[]},{"name":"done","content":[{"name":"move .project file","description":"// Hello there","id":4},{"name":"move config","description":"config from .calcifer/save.json\nto .config/calcifer/state.json","id":1},{"name":"add id to textarea per tab","description":"to improve undo, make each code area of each tab have a unique id (no more undo into another tab)","id":1},{"name":"file tree id ?","description":"// Hello there","id":1},{"name":"open dir in tree ?","description":"// Hello there","id":2},{"name":"fix tab title","description":"// Hello there","id":2},{"name":"when closing last tab","description":"close tab and THEN close calcifer (to save no tab in save.json)","id":1},{"name":"draggable tabs","description":"// Hello there","id":2},{"name":"repair build.rs","description":"// Hello there","id":1},{"name":"export copy paste fix","description":"// Hello there","id":1}]},{"name":"bug","content":[{"name":"ctrl f ","description":"I had crash when going up in the selection","id":1}]},{"name":"+","content":[]}]}
|
|
@ -9,7 +9,7 @@ mkShell {
|
||||||
libXi
|
libXi
|
||||||
pkg-config
|
pkg-config
|
||||||
] ++ [
|
] ++ [
|
||||||
cargo
|
#cargo
|
||||||
rustc
|
rustc
|
||||||
atk
|
atk
|
||||||
gdk-pixbuf
|
gdk-pixbuf
|
||||||
|
@ -19,12 +19,12 @@ mkShell {
|
||||||
libGLU
|
libGLU
|
||||||
libxkbcommon
|
libxkbcommon
|
||||||
gtk3-x11
|
gtk3-x11
|
||||||
gnome.zenity
|
#gnome.zenity
|
||||||
];
|
];
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
latest.rustChannels.stable.rust
|
latest.rustChannels.stable.rust
|
||||||
xorg.libX11
|
xorg.libX11
|
||||||
wayland
|
# wayland
|
||||||
libxkbcommon
|
libxkbcommon
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui::Color32;
|
use egui::Color32;
|
||||||
use std::{cmp::min, fs, path::Path, path::PathBuf};
|
use std::{cmp::max, cmp::min, fs, path::Path, path::PathBuf};
|
||||||
|
|
||||||
use crate::core;
|
use crate::core;
|
||||||
use crate::editor::themes::DEFAULT_THEMES;
|
use crate::editor::themes::DEFAULT_THEMES;
|
||||||
|
@ -45,22 +45,23 @@ impl Calcifer {
|
||||||
pub fn save_tab_as(&self) -> Option<PathBuf> {
|
pub fn save_tab_as(&self) -> Option<PathBuf> {
|
||||||
let default_path = self.home.join("untitled");
|
let default_path = self.home.join("untitled");
|
||||||
|
|
||||||
let save_path = if self.tabs[self.selected_tab].path.file_name().map_or(true, |name| name.to_string_lossy() == "untitled")
|
let save_path = if self.tabs[self.selected_tab]
|
||||||
|
.path
|
||||||
|
.file_name()
|
||||||
|
.map_or(true, |name| name.to_string_lossy() == "untitled")
|
||||||
{
|
{
|
||||||
default_path.to_string_lossy()
|
default_path.to_string_lossy()
|
||||||
} else {
|
} else {
|
||||||
self.tabs[self.selected_tab].path.to_string_lossy()
|
self.tabs[self.selected_tab].path.to_string_lossy()
|
||||||
};
|
};
|
||||||
println!("app : tried to open dialog at {}", save_path);
|
if let Some(path_string) = tinyfiledialogs::save_file_dialog("Save as", &save_path) {
|
||||||
// if let Some(path_string) = tinyfiledialogs::save_file_dialog("Save as", &save_path)
|
let path = PathBuf::from(path_string);
|
||||||
// {
|
if let Err(err) = fs::write(&path, &self.tabs[self.selected_tab].code) {
|
||||||
// let path = PathBuf::from(path_string);
|
eprintln!("Error writing file: {}", err);
|
||||||
// if let Err(err) = fs::write(&path, &self.tabs[self.selected_tab].code) {
|
return None;
|
||||||
// eprintln!("Error writing file: {}", err);
|
}
|
||||||
// return None;
|
return Some(path);
|
||||||
// }
|
}
|
||||||
// return Some(path);
|
|
||||||
// }
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,8 +157,10 @@ impl Calcifer {
|
||||||
|
|
||||||
pub fn delete_tab(&mut self, index: usize) {
|
pub fn delete_tab(&mut self, index: usize) {
|
||||||
self.tabs.remove(index);
|
self.tabs.remove(index);
|
||||||
|
if self.tabs.len() != 0 {
|
||||||
self.selected_tab = min(index, self.tabs.len() - 1);
|
self.selected_tab = min(index, self.tabs.len() - 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toggle(&self, ui: &mut egui::Ui, display: bool, title: &str) -> bool {
|
pub fn toggle(&self, ui: &mut egui::Ui, display: bool, title: &str) -> bool {
|
||||||
let bg_color: Color32;
|
let bg_color: Color32;
|
||||||
|
@ -237,6 +240,10 @@ impl Calcifer {
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tab_area_size(&self) -> usize {
|
||||||
|
max(6, self.tabs.len() + 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unnecessary_lazy_evaluations)]
|
#[allow(clippy::unnecessary_lazy_evaluations)]
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use image::GenericImageView;
|
use image::GenericImageView;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde::Serialize;
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
fs,
|
fs,
|
||||||
|
@ -7,8 +9,6 @@ use std::{
|
||||||
io::Write,
|
io::Write,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Default)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Default)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
|
|
258
src/core/ui.rs
258
src/core/ui.rs
|
@ -1,7 +1,7 @@
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui::{text::CCursor, text_edit::CCursorRange, Rangef};
|
use egui::{text::CCursor, text_edit::CCursorRange, Rangef};
|
||||||
use egui_extras::{Size, StripBuilder};
|
use egui_extras::{Size, StripBuilder};
|
||||||
use std::{cmp::max, env, ffi::OsStr, path::Component, path::Path, path::PathBuf};
|
use std::{cmp::max, cmp::min, env, ffi::OsStr, path::Component, path::Path, path::PathBuf};
|
||||||
|
|
||||||
use crate::core;
|
use crate::core;
|
||||||
use crate::editor;
|
use crate::editor;
|
||||||
|
@ -22,23 +22,37 @@ impl Calcifer {
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
if ui.add(egui::Button::new("📁")).clicked() {
|
if ui.add(egui::Button::new("📁")).clicked() {
|
||||||
println!("ui : open file, wip");
|
if let Some(path_string) = tinyfiledialogs::open_file_dialog(
|
||||||
// if let Some(path_string) = tinyfiledialogs::open_file_dialog("Open File", &self.home.to_string_lossy(), None)
|
"Open File",
|
||||||
// {
|
&self.home.to_string_lossy(),
|
||||||
// self.open_file(Some(&Path::new(&path_string)));
|
None,
|
||||||
// }
|
) {
|
||||||
|
self.open_file(Some(&Path::new(&path_string)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
self.tree_visible = self.toggle(ui, self.tree_visible, "📦");
|
self.tree_visible = self.toggle(ui, self.tree_visible, "📦");
|
||||||
ui.separator();
|
ui.separator();
|
||||||
self.terminal_visible = self.toggle(ui, self.terminal_visible, "🖵");
|
|
||||||
|
let toggle_terminal = self.toggle(ui, self.terminal_visible, "🖵");
|
||||||
|
if toggle_terminal && !self.terminal_visible {
|
||||||
|
let mut path = self.tabs[self.selected_tab].path.clone();
|
||||||
|
path.pop();
|
||||||
|
panels::send_command(format!("cd {}", path.display()));
|
||||||
|
}
|
||||||
|
self.terminal_visible = toggle_terminal;
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
self.search_menu.visible = self.toggle(ui, self.search_menu.visible, "🔍");
|
self.search_menu.visible = self.toggle(ui, self.search_menu.visible, "🔍");
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
self.settings_menu.visible = self.toggle(ui, self.settings_menu.visible, "⚙");
|
self.settings_menu.visible = self.toggle(ui, self.settings_menu.visible, "⚙");
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
self.shortcuts_menu.visible = self.toggle(ui, self.shortcuts_menu.visible, "⌨");
|
self.shortcuts_menu.visible = self.toggle(ui, self.shortcuts_menu.visible, "⌨");
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
self.profiler_visible = self.toggle(ui, self.profiler_visible, "⚡");
|
self.profiler_visible = self.toggle(ui, self.profiler_visible, "⚡");
|
||||||
|
|
||||||
if self.tabs[self.selected_tab].language == PROJECT_EXTENSION {
|
if self.tabs[self.selected_tab].language == PROJECT_EXTENSION {
|
||||||
|
@ -67,7 +81,7 @@ impl Calcifer {
|
||||||
});
|
});
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
let mut init_update : bool = false;
|
let mut init_update: bool = false;
|
||||||
if self.file_tree.is_none() {
|
if self.file_tree.is_none() {
|
||||||
self.file_tree = Some(panels::generate_folder_entry(self.home.as_path()));
|
self.file_tree = Some(panels::generate_folder_entry(self.home.as_path()));
|
||||||
init_update = true
|
init_update = true
|
||||||
|
@ -197,8 +211,8 @@ impl Calcifer {
|
||||||
0.0,
|
0.0,
|
||||||
core::hex_str_to_color(self.theme.bg),
|
core::hex_str_to_color(self.theme.bg),
|
||||||
);
|
);
|
||||||
StripBuilder::new(ui)
|
let response = StripBuilder::new(ui)
|
||||||
.sizes(Size::remainder(), max(6, self.tabs.len() + 1))
|
.sizes(Size::remainder(), self.tab_area_size())
|
||||||
.sense(egui::Sense::click())
|
.sense(egui::Sense::click())
|
||||||
.horizontal(|mut strip| {
|
.horizontal(|mut strip| {
|
||||||
for (index, tab) in self.tabs.clone().iter().enumerate() {
|
for (index, tab) in self.tabs.clone().iter().enumerate() {
|
||||||
|
@ -227,24 +241,18 @@ impl Calcifer {
|
||||||
.clicked()
|
.clicked()
|
||||||
&& !self.close_tab_confirm.visible
|
&& !self.close_tab_confirm.visible
|
||||||
{
|
{
|
||||||
if self.tabs.len() > 1 {
|
|
||||||
if tab.saved {
|
if tab.saved {
|
||||||
self.delete_tab(index);
|
self.delete_tab(index);
|
||||||
} else {
|
} else {
|
||||||
self.close_tab_confirm.ask();
|
self.close_tab_confirm.ask();
|
||||||
self.tab_to_close = index;
|
self.tab_to_close = index;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
egui::Context::send_viewport_cmd(
|
|
||||||
ctx,
|
|
||||||
egui::ViewportCommand::Close,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ui.with_layout(
|
ui.with_layout(
|
||||||
egui::Layout::left_to_right(egui::Align::TOP),
|
egui::Layout::left_to_right(egui::Align::TOP),
|
||||||
|ui| {
|
|ui| {
|
||||||
if ui.add(
|
if ui
|
||||||
|
.add(
|
||||||
egui::Label::new(
|
egui::Label::new(
|
||||||
egui::RichText::new(format!(
|
egui::RichText::new(format!(
|
||||||
" {}{}",
|
" {}{}",
|
||||||
|
@ -256,8 +264,14 @@ impl Calcifer {
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.sense(egui::Sense::click()),
|
.sense(egui::Sense::click()),
|
||||||
)
|
)
|
||||||
.clicked() ||
|
.clicked()
|
||||||
ui.add_sized(ui.available_size(), egui::Label::new("").sense(egui::Sense::click())).clicked()
|
|| ui
|
||||||
|
.add_sized(
|
||||||
|
ui.available_size(),
|
||||||
|
egui::Label::new("")
|
||||||
|
.sense(egui::Sense::click()),
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
{
|
{
|
||||||
self.selected_tab = index;
|
self.selected_tab = index;
|
||||||
}
|
}
|
||||||
|
@ -269,30 +283,32 @@ impl Calcifer {
|
||||||
}
|
}
|
||||||
strip.cell(|ui| {
|
strip.cell(|ui| {
|
||||||
if ui
|
if ui
|
||||||
.add(egui::Label::new(" +").sense(egui::Sense::click()))
|
.add(egui::Label::new(" ➕").sense(egui::Sense::click()))
|
||||||
.clicked()
|
.clicked()
|
||||||
{
|
{
|
||||||
self.open_file(None);
|
self.open_file(None);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
self.tab_rect = response.rect;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_content_panel(&mut self, ctx: &egui::Context) {
|
pub fn draw_content_panel(&mut self, ctx: &egui::Context) {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
ui.horizontal(|ui| {
|
if self.selected_tab >= self.tabs.len() {
|
||||||
if ui
|
return;
|
||||||
.add(egui::Button::new("open directory in terminal"))
|
|
||||||
.clicked()
|
|
||||||
{
|
|
||||||
let mut path = self.tabs[self.selected_tab].path.clone();
|
|
||||||
path.pop();
|
|
||||||
panels::send_command(format!("cd {}", path.display()));
|
|
||||||
}
|
}
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.style_mut().visuals.hyperlink_color =
|
||||||
|
core::hex_str_to_color(self.theme.comments);
|
||||||
if ui
|
if ui
|
||||||
.add(egui::Button::new("expand tree"))
|
.link(
|
||||||
|
self.tabs[self.selected_tab]
|
||||||
|
.path
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
.clicked()
|
.clicked()
|
||||||
{
|
{
|
||||||
let mut current_path = self.tabs[self.selected_tab].path.clone();
|
let mut current_path = self.tabs[self.selected_tab].path.clone();
|
||||||
|
@ -309,14 +325,6 @@ impl Calcifer {
|
||||||
self.tree_visible = true;
|
self.tree_visible = true;
|
||||||
self.file_tree = None;
|
self.file_tree = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.label("Picked file:");
|
|
||||||
ui.monospace(
|
|
||||||
self.tabs[self.selected_tab]
|
|
||||||
.path
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
@ -359,7 +367,7 @@ impl Calcifer {
|
||||||
&mut current_tab.scroll_offset.clone(),
|
&mut current_tab.scroll_offset.clone(),
|
||||||
override_cursor.clone(),
|
override_cursor.clone(),
|
||||||
);
|
);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeEditor::default()
|
CodeEditor::default()
|
||||||
|
@ -386,6 +394,32 @@ impl Calcifer {
|
||||||
.update_from_code(current_tab.code.clone());
|
.update_from_code(current_tab.code.clone());
|
||||||
panels::draw_project(ui, self.theme, &mut self.project_content);
|
panels::draw_project(ui, self.theme, &mut self.project_content);
|
||||||
|
|
||||||
|
self.project_content.selected_item.category = min(
|
||||||
|
self.project_content.categories.len() - 2,
|
||||||
|
self.project_content.selected_item.category,
|
||||||
|
);
|
||||||
|
while self.project_content.categories[self.project_content.selected_item.category]
|
||||||
|
.content
|
||||||
|
.is_empty()
|
||||||
|
&& self.project_content.selected_item.category > 0
|
||||||
|
{
|
||||||
|
self.project_content.selected_item.category -= 1;
|
||||||
|
}
|
||||||
|
if !self.project_content.categories[self.project_content.selected_item.category]
|
||||||
|
.content
|
||||||
|
.is_empty()
|
||||||
|
{
|
||||||
|
self.project_content.selected_item.row = min(
|
||||||
|
self.project_content.categories[self.project_content.selected_item.category]
|
||||||
|
.content
|
||||||
|
.len()
|
||||||
|
- 1,
|
||||||
|
self.project_content.selected_item.row,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.project_content.selected_item.row = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if self.project_content.item_window.visible {
|
if self.project_content.item_window.visible {
|
||||||
if self.project_content.categories.len() > 1
|
if self.project_content.categories.len() > 1
|
||||||
&& !self.project_content.categories[self.project_content.selected_item.category]
|
&& !self.project_content.categories[self.project_content.selected_item.category]
|
||||||
|
@ -401,10 +435,16 @@ impl Calcifer {
|
||||||
|
|
||||||
if delete_item {
|
if delete_item {
|
||||||
self.project_content.item_window.visible = false;
|
self.project_content.item_window.visible = false;
|
||||||
self.project_content.categories
|
self.project_content.categories[self.project_content.selected_item.category]
|
||||||
|
.content
|
||||||
|
.remove(self.project_content.selected_item.row);
|
||||||
|
if self.project_content.selected_item.row
|
||||||
|
>= self.project_content.categories
|
||||||
[self.project_content.selected_item.category]
|
[self.project_content.selected_item.category]
|
||||||
.content.remove(self.project_content.selected_item.row);
|
.content
|
||||||
if self.project_content.selected_item.row >= self.project_content.categories[self.project_content.selected_item.category].content.len() && self.project_content.selected_item.row > 0 {
|
.len()
|
||||||
|
&& self.project_content.selected_item.row > 0
|
||||||
|
{
|
||||||
self.project_content.selected_item.row -= 1;
|
self.project_content.selected_item.row -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -456,6 +496,120 @@ impl Calcifer {
|
||||||
|
|
||||||
self.handle_confirm();
|
self.handle_confirm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn draw_mouse_drag(&mut self, ctx: &egui::Context) {
|
||||||
|
if ctx.input(|i| i.pointer.is_decidedly_dragging()) {
|
||||||
|
if let Some(pos) = ctx.input(|i| i.pointer.interact_pos()) {
|
||||||
|
match self.mouse_holder {
|
||||||
|
panels::MouseHolder::TabHolder(index) => {
|
||||||
|
let snapped_pos = egui::Pos2::new(
|
||||||
|
pos.x,
|
||||||
|
(self.tab_rect.max.y + self.tab_rect.min.y) / 2.0,
|
||||||
|
);
|
||||||
|
|
||||||
|
egui::Area::new(egui::Id::new("mouse_holder"))
|
||||||
|
.fixed_pos(snapped_pos)
|
||||||
|
.show(ctx, |ui| {
|
||||||
|
let (bg_color, text_color) = if self.selected_tab == index {
|
||||||
|
(
|
||||||
|
core::hex_str_to_color(self.theme.functions),
|
||||||
|
core::hex_str_to_color(self.theme.bg),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
core::hex_str_to_color(self.theme.bg),
|
||||||
|
core::hex_str_to_color(self.theme.comments),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let rect = egui::Rect::from_center_size(
|
||||||
|
snapped_pos,
|
||||||
|
egui::Vec2::new(
|
||||||
|
(self.tab_rect.max.x - self.tab_rect.min.x)
|
||||||
|
/ usize_to_f32(self.tab_area_size()),
|
||||||
|
self.tab_rect.max.y - self.tab_rect.min.y,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
ui.painter().rect_filled(rect, 0.0, bg_color);
|
||||||
|
let unsaved_indicator =
|
||||||
|
if self.tabs[index].saved { "" } else { "~ " };
|
||||||
|
|
||||||
|
let _ = ui.put(
|
||||||
|
rect,
|
||||||
|
egui::Label::new(
|
||||||
|
egui::RichText::new(format!(
|
||||||
|
" {}{}",
|
||||||
|
unsaved_indicator,
|
||||||
|
self.tabs[index].get_name()
|
||||||
|
))
|
||||||
|
.color(text_color),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
panels::MouseHolder::None => {
|
||||||
|
if self.tab_rect.distance_to_pos(pos) == 0.0 {
|
||||||
|
let hover_pos: f32 = (pos.x - self.tab_rect.min.x)
|
||||||
|
/ ((self.tab_rect.max.x - self.tab_rect.min.x)
|
||||||
|
/ usize_to_f32(self.tab_area_size()));
|
||||||
|
|
||||||
|
if let Some(index) = floor_f32(hover_pos) {
|
||||||
|
if index < self.tabs.len() {
|
||||||
|
self.mouse_holder = panels::MouseHolder::TabHolder(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.mouse_holder {
|
||||||
|
panels::MouseHolder::TabHolder(initial_index) => {
|
||||||
|
if let Some(pos) = ctx.input(|i| i.pointer.interact_pos()) {
|
||||||
|
let snapped_pos =
|
||||||
|
egui::Pos2::new(pos.x, (self.tab_rect.max.y + self.tab_rect.min.y) / 2.0);
|
||||||
|
if self.tab_rect.distance_to_pos(snapped_pos) == 0.0 {
|
||||||
|
let hover_pos: f32 = (pos.x - self.tab_rect.min.x)
|
||||||
|
/ ((self.tab_rect.max.x - self.tab_rect.min.x)
|
||||||
|
/ usize_to_f32(self.tab_area_size()));
|
||||||
|
|
||||||
|
if let Some(final_index) = floor_f32(hover_pos) {
|
||||||
|
if final_index == initial_index {
|
||||||
|
return;
|
||||||
|
} else if final_index < initial_index {
|
||||||
|
self.tabs
|
||||||
|
.insert(final_index, self.tabs[initial_index].clone());
|
||||||
|
self.tabs.remove(initial_index + 1);
|
||||||
|
} else {
|
||||||
|
self.tabs
|
||||||
|
.insert(final_index + 1, self.tabs[initial_index].clone());
|
||||||
|
self.tabs.remove(initial_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.selected_tab == initial_index {
|
||||||
|
self.selected_tab = final_index;
|
||||||
|
} else if self.selected_tab < initial_index
|
||||||
|
&& self.selected_tab >= final_index
|
||||||
|
{
|
||||||
|
self.selected_tab += 1;
|
||||||
|
} else if self.selected_tab > initial_index
|
||||||
|
&& self.selected_tab <= final_index
|
||||||
|
{
|
||||||
|
self.selected_tab -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panels::MouseHolder::None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mouse_holder = panels::MouseHolder::None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_syntax(language: &str) -> Syntax {
|
fn to_syntax(language: &str) -> Syntax {
|
||||||
|
@ -488,3 +642,21 @@ pub fn format_path(path: &Path) -> String {
|
||||||
.join("/")
|
.join("/")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn usize_to_f32(value: usize) -> f32 {
|
||||||
|
const MAX_F32: f32 = f32::MAX;
|
||||||
|
|
||||||
|
if value as f64 > MAX_F32 as f64 {
|
||||||
|
MAX_F32
|
||||||
|
} else {
|
||||||
|
value as f32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn floor_f32(value: f32) -> Option<usize> {
|
||||||
|
if value.is_nan() || value < 0.0 || value > usize::MAX as f32 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(value.floor() as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,14 +9,79 @@ impl Syntax {
|
||||||
comment: "//",
|
comment: "//",
|
||||||
comment_multiline: ["/*", "*/"],
|
comment_multiline: ["/*", "*/"],
|
||||||
keywords: BTreeSet::from([
|
keywords: BTreeSet::from([
|
||||||
"&&", "||", "!", "let", "var", "abstract", "arguments", "await", "break", "case", "catch", "class", "const", "continue",
|
"&&",
|
||||||
"debugger", "default", "delete", "do", "else", "enum", "eval", "export", "extends", "final", "finally", "for", "function",
|
"||",
|
||||||
"goto", "if", "implements", "import", "in", "instanceof", "interface", "let", "native", "new", "package", "private", "protected",
|
"!",
|
||||||
"public", "return", "static", "super", "switch", "synchronized", "this","throw", "throws", "transient", "try", "typeof",
|
"let",
|
||||||
"var", "volatile", "while", "with", "yield",
|
"var",
|
||||||
|
"abstract",
|
||||||
|
"arguments",
|
||||||
|
"await",
|
||||||
|
"break",
|
||||||
|
"case",
|
||||||
|
"catch",
|
||||||
|
"class",
|
||||||
|
"const",
|
||||||
|
"continue",
|
||||||
|
"debugger",
|
||||||
|
"default",
|
||||||
|
"delete",
|
||||||
|
"do",
|
||||||
|
"else",
|
||||||
|
"enum",
|
||||||
|
"eval",
|
||||||
|
"export",
|
||||||
|
"extends",
|
||||||
|
"final",
|
||||||
|
"finally",
|
||||||
|
"for",
|
||||||
|
"function",
|
||||||
|
"goto",
|
||||||
|
"if",
|
||||||
|
"implements",
|
||||||
|
"import",
|
||||||
|
"in",
|
||||||
|
"instanceof",
|
||||||
|
"interface",
|
||||||
|
"let",
|
||||||
|
"native",
|
||||||
|
"new",
|
||||||
|
"package",
|
||||||
|
"private",
|
||||||
|
"protected",
|
||||||
|
"public",
|
||||||
|
"return",
|
||||||
|
"static",
|
||||||
|
"super",
|
||||||
|
"switch",
|
||||||
|
"synchronized",
|
||||||
|
"this",
|
||||||
|
"throw",
|
||||||
|
"throws",
|
||||||
|
"transient",
|
||||||
|
"try",
|
||||||
|
"typeof",
|
||||||
|
"var",
|
||||||
|
"volatile",
|
||||||
|
"while",
|
||||||
|
"with",
|
||||||
|
"yield",
|
||||||
]),
|
]),
|
||||||
types: BTreeSet::from([
|
types: BTreeSet::from([
|
||||||
"Boolean", "Number", "BigInt", "Undefined", "Null", "String", "Symbol", "byte", "char", "float", "int", "long", "short", "void",
|
"Boolean",
|
||||||
|
"Number",
|
||||||
|
"BigInt",
|
||||||
|
"Undefined",
|
||||||
|
"Null",
|
||||||
|
"String",
|
||||||
|
"Symbol",
|
||||||
|
"byte",
|
||||||
|
"char",
|
||||||
|
"float",
|
||||||
|
"int",
|
||||||
|
"long",
|
||||||
|
"short",
|
||||||
|
"void",
|
||||||
]),
|
]),
|
||||||
special: BTreeSet::from(["false", "null", "true"]),
|
special: BTreeSet::from(["false", "null", "true"]),
|
||||||
}
|
}
|
||||||
|
|
34
src/main.rs
34
src/main.rs
|
@ -4,9 +4,9 @@ use egui::{
|
||||||
TextStyle::{Body, Button, Heading, Monospace, Small},
|
TextStyle::{Body, Button, Heading, Monospace, Small},
|
||||||
};
|
};
|
||||||
use homedir::get_my_home;
|
use homedir::get_my_home;
|
||||||
use std::{ops::Range, path::PathBuf, sync::Arc, thread, time};
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use std::{ops::Range, path::PathBuf, sync::Arc, thread, time};
|
||||||
|
|
||||||
mod core;
|
mod core;
|
||||||
mod editor;
|
mod editor;
|
||||||
|
@ -25,7 +25,13 @@ const TERMINAL_HEIGHT: f32 = 200.0;
|
||||||
const TERMINAL_RANGE: Range<f32> = 100.0..600.0;
|
const TERMINAL_RANGE: Range<f32> = 100.0..600.0;
|
||||||
const RED: egui::Color32 = egui::Color32::from_rgb(235, 108, 99);
|
const RED: egui::Color32 = egui::Color32::from_rgb(235, 108, 99);
|
||||||
const TIME_LABELS: [&str; 7] = [
|
const TIME_LABELS: [&str; 7] = [
|
||||||
"input", "settings", "tree", "terminal", "tabs", "content", "windows",
|
"input",
|
||||||
|
"settings",
|
||||||
|
"tree",
|
||||||
|
"terminal+tray",
|
||||||
|
"tabs",
|
||||||
|
"content",
|
||||||
|
"windows",
|
||||||
];
|
];
|
||||||
const ZOOM_FACTOR: f32 = 1.1;
|
const ZOOM_FACTOR: f32 = 1.1;
|
||||||
const MAX_FPS: f32 = 30.0;
|
const MAX_FPS: f32 = 30.0;
|
||||||
|
@ -63,6 +69,8 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//panels::send_command("export RUSTFLAGS=--cfg=web_sys_unstable_apis".to_string());
|
||||||
|
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
&format!("Calcifer{}", TITLE),
|
&format!("Calcifer{}", TITLE),
|
||||||
options,
|
options,
|
||||||
|
@ -76,6 +84,8 @@ struct Calcifer {
|
||||||
|
|
||||||
selected_tab: usize,
|
selected_tab: usize,
|
||||||
tabs: Vec<panels::Tab>,
|
tabs: Vec<panels::Tab>,
|
||||||
|
tab_rect: egui::Rect,
|
||||||
|
mouse_holder: panels::MouseHolder,
|
||||||
|
|
||||||
command: String,
|
command: String,
|
||||||
command_history: Vec<panels::CommandEntry>,
|
command_history: Vec<panels::CommandEntry>,
|
||||||
|
@ -117,6 +127,8 @@ impl Default for Calcifer {
|
||||||
|
|
||||||
selected_tab: 0,
|
selected_tab: 0,
|
||||||
tabs: vec![panels::Tab::default()],
|
tabs: vec![panels::Tab::default()],
|
||||||
|
tab_rect: egui::Rect::EVERYTHING,
|
||||||
|
mouse_holder: panels::MouseHolder::None,
|
||||||
|
|
||||||
command: String::new(),
|
command: String::new(),
|
||||||
command_history: Vec::new(),
|
command_history: Vec::new(),
|
||||||
|
@ -201,7 +213,8 @@ impl eframe::App for Calcifer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.input(|i| i.key_pressed(egui::Key::Enter)) && ctx.memory(|m| m.focus() == None)
|
if ctx.input(|i| i.key_pressed(egui::Key::Enter))
|
||||||
|
&& ctx.memory(|m| m.focus() == None)
|
||||||
&& self.tabs[self.selected_tab].language == PROJECT_EXTENSION
|
&& self.tabs[self.selected_tab].language == PROJECT_EXTENSION
|
||||||
{
|
{
|
||||||
self.project_content.item_window.visible = true;
|
self.project_content.item_window.visible = true;
|
||||||
|
@ -224,11 +237,11 @@ impl eframe::App for Calcifer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.input(|i| i.zoom_delta() > 1.0) {
|
if ctx.input(|i| i.zoom_delta() > 1.0) {
|
||||||
self.zoom = (self.zoom*ZOOM_FACTOR).min(10.0);
|
self.zoom = (self.zoom * ZOOM_FACTOR).min(10.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.input(|i| i.zoom_delta() < 1.0) {
|
if ctx.input(|i| i.zoom_delta() < 1.0) {
|
||||||
self.zoom = (self.zoom/ZOOM_FACTOR).max(0.1);
|
self.zoom = (self.zoom / ZOOM_FACTOR).max(0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.input(|i| i.key_pressed(egui::Key::F) && i.modifiers.ctrl) {
|
if ctx.input(|i| i.key_pressed(egui::Key::F) && i.modifiers.ctrl) {
|
||||||
|
@ -267,6 +280,11 @@ impl eframe::App for Calcifer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.tabs.len() == 0 {
|
||||||
|
egui::Context::send_viewport_cmd(ctx, egui::ViewportCommand::Close);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.time_watch[0] = watch.elapsed().as_micros() as f32 / 1000.0;
|
self.time_watch[0] = watch.elapsed().as_micros() as f32 / 1000.0;
|
||||||
watch = time::Instant::now();
|
watch = time::Instant::now();
|
||||||
|
|
||||||
|
@ -297,11 +315,15 @@ impl eframe::App for Calcifer {
|
||||||
watch = time::Instant::now();
|
watch = time::Instant::now();
|
||||||
|
|
||||||
self.draw_windows(ctx);
|
self.draw_windows(ctx);
|
||||||
|
self.draw_mouse_drag(ctx);
|
||||||
|
|
||||||
self.time_watch[6] = watch.elapsed().as_micros() as f32 / 1000.0;
|
self.time_watch[6] = watch.elapsed().as_micros() as f32 / 1000.0;
|
||||||
|
|
||||||
if self.running_command {
|
if self.running_command {
|
||||||
egui::Context::request_repaint_after(ctx, Duration::from_secs_f32(RUNNING_COMMAND_REFRESH_DELAY));
|
egui::Context::request_repaint_after(
|
||||||
|
ctx,
|
||||||
|
Duration::from_secs_f32(RUNNING_COMMAND_REFRESH_DELAY),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
|
use std::hash::DefaultHasher;
|
||||||
|
use std::hash::Hash;
|
||||||
|
use std::hash::Hasher;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
use std::time::UNIX_EPOCH;
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
fs, io,
|
fs, io,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
use std::hash::DefaultHasher;
|
|
||||||
use std::time::UNIX_EPOCH;
|
|
||||||
use std::time::SystemTime;
|
|
||||||
use std::hash::Hasher;
|
|
||||||
use std::hash::Hash;
|
|
||||||
|
|
||||||
//use crate::ALLOWED_FILE_EXTENSIONS;
|
//use crate::ALLOWED_FILE_EXTENSIONS;
|
||||||
|
|
||||||
|
@ -42,7 +42,10 @@ impl FileEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_unique_id(path: PathBuf) -> String {
|
fn generate_unique_id(path: PathBuf) -> String {
|
||||||
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
|
let now = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs();
|
||||||
|
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
now.hash(&mut hasher);
|
now.hash(&mut hasher);
|
||||||
|
@ -147,10 +150,10 @@ fn generate_entry(path: &Path) -> Option<FileEntry> {
|
||||||
if file_name.to_string_lossy().starts_with('.') {
|
if file_name.to_string_lossy().starts_with('.') {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
// let extension = path.extension().and_then(|ext| ext.to_str());
|
// let extension = path.extension().and_then(|ext| ext.to_str());
|
||||||
// if !ALLOWED_FILE_EXTENSIONS.contains(&extension.unwrap_or_default()) {
|
// if !ALLOWED_FILE_EXTENSIONS.contains(&extension.unwrap_or_default()) {
|
||||||
// return None;
|
// return None;
|
||||||
// }
|
// }
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::min,
|
|
||||||
cmp::max,
|
cmp::max,
|
||||||
sync::atomic::{AtomicUsize, Ordering},
|
sync::atomic::{AtomicUsize, Ordering},
|
||||||
};
|
};
|
||||||
|
@ -124,7 +123,9 @@ fn get_id() -> usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_project(ui: &mut egui::Ui, theme: ColorTheme, project: &mut Project) {
|
pub fn draw_project(ui: &mut egui::Ui, theme: ColorTheme, project: &mut Project) {
|
||||||
ui.columns(max(MAX_PROJECT_COLUMNS, project.categories.len() + 1) , |uis| {
|
ui.columns(
|
||||||
|
max(MAX_PROJECT_COLUMNS, project.categories.len() + 1),
|
||||||
|
|uis| {
|
||||||
for (category_index, category) in project.categories.clone().into_iter().enumerate() {
|
for (category_index, category) in project.categories.clone().into_iter().enumerate() {
|
||||||
let ui = &mut uis[category_index];
|
let ui = &mut uis[category_index];
|
||||||
|
|
||||||
|
@ -152,7 +153,8 @@ pub fn draw_project(ui: &mut egui::Ui, theme: ColorTheme, project: &mut Project)
|
||||||
row: item_index,
|
row: item_index,
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
ui.style_mut().visuals.override_text_color = Some(hex_str_to_color(theme.bg));
|
ui.style_mut().visuals.override_text_color =
|
||||||
|
Some(hex_str_to_color(theme.bg));
|
||||||
ui.add(
|
ui.add(
|
||||||
egui::Button::new(item.name.clone())
|
egui::Button::new(item.name.clone())
|
||||||
.fill(hex_str_to_color(theme.functions)),
|
.fill(hex_str_to_color(theme.functions)),
|
||||||
|
@ -161,7 +163,10 @@ pub fn draw_project(ui: &mut egui::Ui, theme: ColorTheme, project: &mut Project)
|
||||||
ui.style_mut().visuals.override_text_color =
|
ui.style_mut().visuals.override_text_color =
|
||||||
Some(hex_str_to_color(theme.literals));
|
Some(hex_str_to_color(theme.literals));
|
||||||
if ui
|
if ui
|
||||||
.add(egui::Button::new(item.name.clone()).fill(hex_str_to_color(theme.bg)))
|
.add(
|
||||||
|
egui::Button::new(item.name.clone())
|
||||||
|
.fill(hex_str_to_color(theme.bg)),
|
||||||
|
)
|
||||||
.clicked()
|
.clicked()
|
||||||
{
|
{
|
||||||
project.selected_item = Location {
|
project.selected_item = Location {
|
||||||
|
@ -171,22 +176,15 @@ pub fn draw_project(ui: &mut egui::Ui, theme: ColorTheme, project: &mut Project)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui.style_mut().visuals.override_text_color =
|
ui.style_mut().visuals.override_text_color = Some(hex_str_to_color(theme.literals));
|
||||||
Some(hex_str_to_color(theme.literals));
|
|
||||||
if category.name != "+" && ui.add(egui::Button::new("+")).clicked() {
|
if category.name != "+" && ui.add(egui::Button::new("+")).clicked() {
|
||||||
project.categories[category_index]
|
project.categories[category_index]
|
||||||
.content
|
.content
|
||||||
.push(Item::new("item"));
|
.push(Item::new("item"));
|
||||||
}
|
}
|
||||||
// if category.name != "+" {
|
|
||||||
// if ui.add(egui::Button::new("+")).clicked() {
|
|
||||||
// project.categories[category_index]
|
|
||||||
// .content
|
|
||||||
// .push(Item::new("item"));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let mut moved = false;
|
let mut moved = false;
|
||||||
let category = project.selected_item.category;
|
let category = project.selected_item.category;
|
||||||
|
@ -238,23 +236,15 @@ pub fn draw_project(ui: &mut egui::Ui, theme: ColorTheme, project: &mut Project)
|
||||||
&& project.selected_item.category > 0
|
&& project.selected_item.category > 0
|
||||||
{
|
{
|
||||||
moved = true;
|
moved = true;
|
||||||
if !project.was_moving {
|
if !project.was_moving && project.categories[category - 1].content.len() > 0 {
|
||||||
project.selected_item.category -= 1;
|
project.selected_item.category -= 1;
|
||||||
project.selected_item.row = min(
|
|
||||||
project.categories[category].content.len() - 1,
|
|
||||||
project.selected_item.row,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else if ui.input(|i| i.key_pressed(egui::Key::ArrowRight))
|
} else if ui.input(|i| i.key_pressed(egui::Key::ArrowRight))
|
||||||
&& project.selected_item.category < project.categories.len() - 2
|
&& project.selected_item.category < project.categories.len() - 2
|
||||||
{
|
{
|
||||||
moved = true;
|
moved = true;
|
||||||
if !project.was_moving {
|
if !project.was_moving && project.categories[category + 1].content.len() > 0 {
|
||||||
project.selected_item.category += 1;
|
project.selected_item.category += 1;
|
||||||
project.selected_item.row = min(
|
|
||||||
project.categories[category].content.len() - 1,
|
|
||||||
project.selected_item.row,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else if ui.input(|i| i.key_pressed(egui::Key::ArrowUp)) && project.selected_item.row > 0 {
|
} else if ui.input(|i| i.key_pressed(egui::Key::ArrowUp)) && project.selected_item.row > 0 {
|
||||||
moved = true;
|
moved = true;
|
||||||
|
|
|
@ -61,6 +61,11 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum MouseHolder {
|
||||||
|
TabHolder(usize),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
fn read_file_contents(path: &Path) -> String {
|
fn read_file_contents(path: &Path) -> String {
|
||||||
let error_type = "reading file";
|
let error_type = "reading file";
|
||||||
read_to_string(path)
|
read_to_string(path)
|
||||||
|
|
|
@ -22,10 +22,10 @@ impl ProjectItemWindow {
|
||||||
|
|
||||||
if let Some(response) = maybe_response {
|
if let Some(response) = maybe_response {
|
||||||
if let Some(delete_option) = response.inner {
|
if let Some(delete_option) = response.inner {
|
||||||
return delete_option
|
return delete_option;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui(&mut self, ui: &mut egui::Ui, item: &mut panels::Item) -> bool {
|
fn ui(&mut self, ui: &mut egui::Ui, item: &mut panels::Item) -> bool {
|
||||||
|
@ -43,6 +43,6 @@ impl ProjectItemWindow {
|
||||||
ui.available_size(),
|
ui.available_size(),
|
||||||
egui::TextEdit::multiline(&mut item.description),
|
egui::TextEdit::multiline(&mut item.description),
|
||||||
);
|
);
|
||||||
return delete_item.clone()
|
return delete_item.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue